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 }
View Code

 

posted @ 2018-08-03 19:59  Xu-daxia  阅读(259)  评论(0编辑  收藏  举报