POJ 2455 Secret Milking Machine 【二分】+【最大流】

<题目链接>

题目大意:

FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l。现在要你找出从第1块地到第n块地的T条不同路径,每条路径上的路段不能与先前的路径重复,问这些路径中的最长路段的最小值是多少。

解题分析:

最小的最大值问题,依然需要用二分答案,枚举出该最大路段的长度,然后将所有小于等于这个值得路段加入网络,将这些路段的容量置为1。因为是无向图,所以正、反向弧的容量都置为1,之后跑一遍最大流,再根据最大流和T的大小关系来判断。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define INF 0x3f3f3f3f
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 const int N=210;
10 
11 struct Edge{
12     int u,v,c;
13 }edge[N*N*2];
14 
15 struct Segment{
16     int a,b,len;
17 }seg[N*N];
18 
19 int d[N],cur[N];
20 int head[N],next[N*N*2];
21 int n,m,k,maxlen,minlen,cnt;
22 
23 void addedge(int u,int v,int w){
24     edge[cnt].u=u;edge[cnt].v=v,edge[cnt].c=w;
25     next[cnt]=head[u],head[u]=cnt++;
26 
27     edge[cnt].u=v;edge[cnt].v=u,edge[cnt].c=w;
28     next[cnt]=head[v],head[v]=cnt++;
29 }
30 
31 int bfs(int s,int t){
32     queue<int> q;
33     mem(d,0);
34     d[s]=1;
35     q.push(s);
36     while(!q.empty()){
37         int x=q.front();q.pop();
38         for(int i=head[x];i!=-1;i=next[i]){
39             if(edge[i].c>0 && !d[edge[i].v]){
40                 d[edge[i].v]=d[x]+1;
41                 q.push(edge[i].v);
42             }
43         }
44     }
45     return d[t];
46 }
47 
48 int dfs(int x,int a){
49     if(x==n || a==0)return a;
50     int t,f,flow=0;
51     for(int& i=cur[x];i!=-1;i=next[i]){
52         if(d[x]+1==d[edge[i].v] && (f=dfs(edge[i].v,min(a,edge[i].c)))>0){
53             edge[i].c-=f;
54             edge[i^1].c+=f;
55             flow+=f;
56             a-=f;
57             if(!a)break;
58         }
59     }
60     return flow;
61 }
62 
63 int dinic(int s,int t,int limit){
64     int i,ret=0;
65     while(bfs(s,t)){
66         for(i=1;i<=n;i++)cur[i]=head[i];
67         ret+=dfs(s,INF);
68     }
69     return ret;
70 }
71 
72 int binary_solve(){
73     int low=minlen,high=maxlen;
74     while(low<high){        //这个二分答案部分对格式还是有点疑惑
75         int mid=(low+high)>>1;
76         cnt=0;mem(head,-1);    //init()
77         for(int i=0;i<m;i++)   //加入所有满足要求的边
78             if(seg[i].len<=mid)
79                 addedge(seg[i].a,seg[i].b,1);
80         int t=dinic(1,n,mid);
81         if(t<k)low=mid+1;
82         else high=mid;
83     }
84     return low;
85 }
86 
87 int main(){
88     while(~scanf("%d%d%d",&n,&m,&k)){
89         maxlen=-INF;minlen=INF;
90         for(int i=0;i<m;i++){
91             scanf("%d%d%d",&seg[i].a,&seg[i].b,&seg[i].len);
92             maxlen=max(maxlen,seg[i].len);
93             minlen=min(minlen,seg[i].len);
94         }
95         printf("%d\n",binary_solve());
96     }
97     return 0;
98 }

2018-11-24

猜你喜欢

转载自www.cnblogs.com/00isok/p/10014113.html