60pts,WA#4,5,6,9,10,无TLE
大致原理:第一问EK算法最大流,第二问在1的基础上每个边权乘以一个常量并+1,用1的微差比较边数,且不影响最终结果;
问题代码见下:
#include<bits/stdc++.h>
#define N 0x7f7f7f7f7f
using namespace std;
long long C1[500][500];
bool visit[500],cata[500][500];
int pre[1001];
int n,m,t=0;//n点m边
long long int ans=0;
inline bool bfs(){
memset(visit,0,sizeof(visit));
memset(pre,0,sizeof(pre));
visit[1]=1;
pre[1]=0;//此处的0作为回溯终止的标记
queue<int> q;
q.push(1);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=1;i<=n+t;i++){
if(!visit[i]&&C1[x][i]>0){
pre[i]=x;//边走边记路径
if(i==n) return 1;
else{
visit[i]=1;
q.push(i);
}
}
}
}
return 0;
}
inline void giao(){
while(bfs()){
long long ton=N;
for(int i=n;pre[i]!=0;i=pre[i]){
ton=min(ton,C1[pre[i]][i]);
}
for(int i=n;pre[i]!=0;i=pre[i]){
C1[pre[i]][i]-=ton;
C1[i][pre[i]]+=ton;
}
ans+=ton;
continue;
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
C1[a][b]+=c;
}
for(int i=1;i<=n;i++){//本输入不能处理给定的双向边,所以要通过加点的方式把双向边a←→b处理成a→b,a←c←b,使之不干扰EK算法的工作原理
for(int j=1;j<=n&&j!=i;j++){
if((C1[i][j]>0)&&(C1[j][i]>0)){
t++;
C1[j][n+t]=C1[j][i];
C1[n+t][i]=C1[j][i];
C1[j][i]=0;
}
}
}
for(int i=1;i<=n+t;i++){
for(int j=1;j<=n+t;j++){
if(C1[i][j]>0){
C1[i][j]=C1[i][j]*32767+1;//稳流法,用乘大数的方式统一最大流相同时的情况,用加一来区分割边数
}
}
}
giao();
cout<<ans/32767<<" "<<ans%32767;
return 0;
}