生活随笔
收集整理的這篇文章主要介紹了
Uvaoj 11248 Frequency Hopping(Dinic求最小割)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:1到n節(jié)點(diǎn)(節(jié)點(diǎn)之間有一定的容量),需要流過C的流量,問是否可以?如果可以輸出possible, 否則如果可以擴(kuò)大任意一條邊的容量
可以達(dá)到目的,那么輸出possible option:接著輸出每一條可以達(dá)到目的的邊(按升序),再否則輸出not possible
思路:先求一次最大流,如果流量至少為C,則直接輸出possible,否則需要修改的弧一定在最小割里!
接著吧這些弧(最小割里的)的容量設(shè)為無窮大,然后在求最大流,看最大流的流量能否滿足是C即可,如果滿足了,那就把這一條邊記錄下來
分析:最大流的程序沒有必要完全的執(zhí)行完畢,知道當(dāng)前的流量>=C那么就可以中止最大流的程序!
還有就是第一次的最大流程序如果沒有找到>=C的最大流,那么此時的流量留著,下一次在最小割里擴(kuò)容的時候,總是接著第一次Dinic的流量
繼續(xù)尋找....
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<algorithm>
5 #include<vector>
6 #include<queue>
7 #define N 105
8 #define INF 2000000005
9 using namespace std;
10
11 struct EDGE{
12 int u, v, nt, cap;
13 bool flag;
14 bool vis;
15 EDGE(){}
16 EDGE(
int u,
int v,
int nt,
int cap,
bool flag):u(u), v(v), nt(nt), cap(cap), flag(flag){}
17 };
18
19 struct node{
20 int x, y;
21 node(){}
22 node(
int x,
int y) : x(x), y(y){}
23 };
24
25 int pos[
10005];
26
27 node ans[
10005];
28 int preCost[
20005];
29 int vis[
20005];
30 int p[
20005];
31 int pcnt;
32 int cnt;
33
34 vector<EDGE>
g;
35 int first[N];
36
37 int d[N];
38 int n, e, c;
39
40 void addEdge(
int u,
int v,
int c){
41 g.push_back(EDGE(u, v, first[u], c,
true));
42 first[u] = g.size() -
1;
43 g.push_back(EDGE(v, u, first[v],
0,
false));
44 first[v] = g.size() -
1;
45 }
46
47 bool bfs(){
48 memset(d,
0,
sizeof(d));
49 d[
1] =
1;
50 queue<
int>
q;
51 q.push(
1);
52 while(!
q.empty()){
53 int u =
q.front();
54 q.pop();
55 for(
int i = first[u]; ~i; i =
g[i].nt){
56 int v =
g[i].v;
57 if(!d[v] && g[i].cap >
0){
58 d[v] = d[u] +
1;
59 q.push(v);
60 }
61 }
62 }
63 if(d[n] ==
0)
return false;
64 return true;
65 }
66
67 bool cmp(node a, node b){
68 if(a.x ==
b.x)
69 return a.y <
b.y;
70 return a.x <
b.x;
71 }
72
73 int leave;
74
75 int dfs(
int u,
int totf){
76 int flow =
0;
77 if(u ==n || totf==
0)
return totf;
78 for(
int i = first[u]; ~i; i =
g[i].nt){
79 int v =
g[i].v;
80 if(d[v] == d[u] +
1 && g[i].cap >
0){
81 int ff = dfs(v, min(totf-
flow, g[i].cap));
82 if(ff >
0){
83 if(!
vis[i]){
84 p[pcnt++]=
i;
85 preCost[i] =
g[i].cap;
86 vis[i] =
1;
87 }
88 g[i].cap -=
ff;
89
90 if(!vis[i^
1]){
91 p[pcnt++]=i^
1;
92 preCost[i^
1] = g[i^
1].cap;
93 vis[i^
1] =
1;
94 }
95 g[i^
1].cap +=
ff;
96 flow +=
ff;
97
98 if(flow >=
leave){
99 flow =
leave;
100 return flow;
101 }
102
103 if(totf == flow)
break;
104 }
105 else d[v] = -
1;
106 }
107 }
108 return flow;
109 }
110
111 bool Dinic(){
112 leave =
c;
113 while(bfs()){
114 leave -= dfs(
1, INF);
115 if(leave ==
0)
break;
116 }
117 if(leave ==
0)
return true;
118 return false;
119 }
120
121
122
123 int main(){
124 int cas =
0;
125 while(scanf(
"%d%d%d", &n, &e, &
c)){
126 if(!n)
break;
127 memset(first, -
1,
sizeof(first));
128 g.clear();
129 cnt =
0;
130 while(e--
){
131 int x, y, z;
132 scanf(
"%d%d%d", &x, &y, &
z);
133 addEdge(x, y, z);
134 }
135 printf(
"Case %d: ", ++cas);
//這一塊差點(diǎn)沒有把我氣死...居然有一個空格,沒有看清楚啊...一直PE.
136
137 if(n==
1){
138 printf(
"possible\n");
139 continue;
140 }
141
142 if(Dinic()) printf(
"possible\n");
143 else{
144 int len =
g.size();
145 for(
int i=
0; i<len; ++
i)
146 if(g[i].cap ==
0 &&
g[i].flag)
147 pos[cnt++] = i;
//得到最小割
148 int cc = leave;
//第一次Dinic之后,還剩下多少的流量需要流過
149 int ret =
0;
150 for(
int i=
0; i<cnt; ++
i){
151 c = cc;
//新的需要流過的流量
152 pcnt =
0;
153 g[pos[i]].cap =
INF;
154 memset(vis,
0,
sizeof(vis));
155 if(Dinic())
//如果增廣成功,那么這條最小割滿足
156 ans[ret++] =
node(g[pos[i]].u, g[pos[i]].v);
157 for(
int j=
0; j<pcnt; ++
j)
158 g[p[j]].cap = preCost[p[j]];
//將Dinic中所經(jīng)過的邊的值恢復(fù)成第一次Dinic之后的值!
159 g[pos[i]].cap =
0;
160 }
161 if( ret >
0 ){
162 sort(ans, ans+
ret, cmp);
163 printf(
"possible option:(%d,%d)", ans[
0].x, ans[
0].y);
164 for(
int i=
1; i<ret; ++
i)
165 printf(
",(%d,%d)", ans[i].x, ans[i].y);
166 printf(
"\n");
167 }
168 else printf(
"not possible\n");
169 }
170 }
171 return 0;
172 }
View Code ?
轉(zhuǎn)載于:https://www.cnblogs.com/hujunzheng/p/4014923.html
總結(jié)
以上是生活随笔為你收集整理的Uvaoj 11248 Frequency Hopping(Dinic求最小割)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。