luoguP1401 城市(二分答案+最大流)
题意
N(2<=n<=200)个城市,M(1<=m<=40000)条无向边,你要找T(1<=T<=200)条从城市1到城市N的路,使得最长的边的长度最小,边不能重复用。
题解
简单的网络流判定。
一看问法想到二分答案。然后边不能重复直接上网络流。
(用边长小于mid的边建图然后跑最大流,最后比较流量和k)
(然而不知为何写挂了)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define find_min(a,b) a<b?a:b 5 #define find_max(a,b) a>b?a:b 6 7 using namespace std; 8 9 const int N = 210; 10 const int MAX = (int)10e7; 11 12 struct Edge{ 13 int s,e,v,next; 14 }edge[2*N*N],mat[N*N]; 15 16 int e_num,head[N],d[N],sp,tp; 17 int n,m; 18 19 void AddEdge(int a,int b,int c){ 20 edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c; 21 edge[e_num].next=head[a]; head[a]=e_num++; 22 23 edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c; 24 edge[e_num].next=head[b]; head[b]=e_num++; 25 } 26 27 int bfs(){ 28 queue <int> q; 29 memset(d,-1,sizeof(d)); 30 d[sp]=0; 31 q.push(sp); 32 while(!q.empty()){ 33 int cur=q.front(); 34 q.pop(); 35 for(int i=head[cur];i!=-1;i=edge[i].next){ 36 int u=edge[i].e; 37 if(d[u]==-1 && edge[i].v>0){ 38 d[u]=d[cur]+1; 39 q.push(u); 40 } 41 } 42 } 43 return d[tp] != -1; 44 } 45 46 int dfs(int a,int b){ 47 int r=0; 48 if(a==tp)return b; 49 for(int i=head[a];i!=-1 && r<b;i=edge[i].next){ 50 int u=edge[i].e; 51 if(edge[i].v>0 && d[u]==d[a]+1){ 52 int x=find_min(edge[i].v,b-r); 53 x=dfs(u,x); 54 r+=x; 55 edge[i].v-=x; 56 edge[i^1].v+=x; 57 } 58 } 59 if(!r)d[a]=-2; 60 return r; 61 } 62 63 int dinic(int sp,int tp){ 64 int total=0,t; 65 while(bfs()){ 66 while(t=dfs(sp,MAX)) 67 total+=t; 68 } 69 return total; 70 } 71 void init(int index){ 72 int i,j; 73 e_num=0; 74 memset(head,-1,sizeof(head)); 75 for(i=1;i<=m;i++){ 76 if(mat[i].v<=index)AddEdge(mat[i].s,mat[i].e,1); 77 } 78 } 79 80 int main() 81 { 82 int t_num,i,j,a,b,c; 83 while(~scanf("%d%d%d",&n,&m,&t_num)){ 84 sp=1;tp=n; 85 int high=-1,low=MAX; 86 for(i=1;i<=m;i++){ 87 scanf("%d%d%d",&a,&b,&c); 88 high=find_max(high,c); 89 low=find_min(low,c); 90 mat[i].s=a; mat[i].e=b; mat[i].v=c; 91 } 92 int mid,ans; 93 while(low<=high){ 94 mid=(low+high)/2; 95 init(mid); 96 ans=dinic(sp,tp); 97 if(ans<t_num)low=mid+1; 98 else high=mid-1; 99 } 100 printf("%d\n",low); 101 } 102 return 0; 103 }