USACO 4.4.2 milk6
题目:
http://ace.delos.com/usacoprob2?a=H4mXhbyi4yi&S=milk6
http://www.nocow.cn/index.php/Translate:USACO/milk6
Hal Burch
It's your first day in Quality Control at Merry Milk Makers, and already there's been a catastrophe: a shipment of bad milk has been sent out. Unfortunately, you didn't discover this until the milk was already into your delivery system on its way to stores. You know which grocer that milk was destined for, but there may be multiple ways for the milk to get to that store.
The delivery system is made up of a several warehouses, with trucks running from warehouse to warehouse moving milk. While the milk will be found quickly, it is important that it does not make it to the grocer, so you must shut down enough trucks to ensure that it is impossible for the milk to get to the grocer in question. Every route costs a certain amount to shut down. Find the minimum amount that must be spent to ensure the milk does not reach its destination, along with a set of trucks to shut down that achieves this goal at that cost.
PROGRAM NAME: milk6
INPUT FORMAT
Line 1: | Two space separated integers, N and M. N (2 <= N <= 32) is the number of warehouses that Merry Milk Makers has, and M (0 <= M <= 1000) is the number of trucks routes run. Warehouse 1 is actually the productional facility, while warehouse N is the grocer to which which the bad milk was destined. |
Line 2..M+1: | Truck routes: three space-separated integers, Si, Ei, and Ci. Si and Ei (1 <= Si,Ei <= N) correspond to the pickup warehouse and dropoff warehouse for the truck route. Ci (0 <= Ci <= 2,000,000) is the cost of shutting down the truck route. |
SAMPLE INPUT (file milk6.in)
4 5
1 3 100
3 2 50
2 4 60
1 2 40
2 3 80
OUTPUT FORMAT
The first line of the output should be two integers, C and T. C is the minimum amount which must be spent in order to ensure the our milk never reaches its destination. T is the minimum number of truck routes that you plan to shut down in order to achive this goal. The next T lines sould contain a sorted list of the indexes of the truck routes that you suggest shutting down. If there are multiple sets of truck routes that achieve the goal at minimum cost, choose one that shuts down the minimum number of routes. If there are still multiple sets, choose the one whose initial routes have the smallest index.
SAMPLE OUTPUT (file milk6.out)
60 1 3
题解:
这题与第五章某道题相似,那道题是删点,这道题是删边,然后那道题我很容易过了,这道题我就写疯了…………………………
把权值当做流量来建边,这样做一道网络流后我们便可以知道最少代价是多少了,解决第一问。
第二问要求边最少,解决方案是每条边的权值变为1001*v+1,这样一来对于以下这种情况:
便会选取1->2的边而不会选取2->3和2->4这两条边(原谅画图和鼠标的问题),于是第二问解决。(具体证明可以自行yy,这里只是给了一个例子)
对于第三问,要求字典序最小,考虑两种情况:
1、有割边。
2、无割边。
对于第一种情况,把最小字典序割边找出来即可,这个不难……………………对于第二种情况,我们从头开始枚举,每次删除一条边,如果删除该边后对流量有影响,那么说明该边为要选取的边,即做m次网络流……………………第三问解决。
注意:
1、写非递归的网络流,递归的T了。(这个问题有可能是我递归的写的有问题而导致的)
2、DFS的迭代加深MS不科学,不推荐。
3、64位整数。
1 /*
2 ID:zhongh1
3 PROB:milk6
4 LANG:C++
5 */
6
7 #include<cstdio>
8 #include<cstdlib>
9 #include<cstring>
10 #include<queue>
11
12 using namespace std;
13
14 const int maxn=40;
15 const int maxm=2001;
16 const int INF=12345678912345678ll;
17
18 int s,e,d[maxn],en,n,m,l,x[maxm],y[maxm],stack[maxn];
19
20 long long ans,z[maxm];
21
22 bool use[maxm],use2[maxn];
23
24 queue<int> que;
25
26 struct edge
27 {
28 int e;
29 long long f;
30 edge *op,*next;
31 }ed[maxm],*v[maxn],*fe[maxn],*p[maxn];
32
33 void add_edge(int s,int e,int f)
34 {
35 en++;
36 ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->f=f;
37 en++;
38 ed[en].next=v[e];v[e]=ed+en;v[e]->e=s;v[e]->f=0;
39 v[s]->op=v[e];v[e]->op=v[s];
40 }
41
42 void add_edge2(int s,int e)
43 {
44 en++;
45 ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
46 }
47
48 bool bfs()
49 {
50 memset(d,-1,sizeof(d));
51 while (que.size())
52 que.pop();
53 que.push(s);
54 d[s]=0;
55 while (que.size())
56 {
57 int now=que.front();
58 que.pop();
59 for (edge *e=v[now];e;e=e->next)
60 if (d[e->e]==-1 && e->f)
61 {
62 d[e->e]=d[now]+1;
63 que.push(e->e);
64 }
65 }
66 return d[e]!=-1;
67 }
68
69 long long dfs(int now,long long cur_flow)
70 {
71 if (now==e) return cur_flow;
72 long long rest=cur_flow;
73 for (edge *e=v[now];e;e=e->next)
74 if (d[e->e]==d[now]+1 && e->f)
75 {
76 long long new_flow=dfs(e->e,min(rest,e->f));
77 e->f-=new_flow;
78 e->op->f+=new_flow;
79 rest-=new_flow;
80 }
81 return cur_flow-rest;
82 }
83
84 bool dfs3(int now)
85 {
86 if (now==e) return true;
87 use2[now]=true;
88 for (edge *e=v[now];e;e=e->next)
89 if (!use2[e->e])
90 {
91 if (dfs3(e->e)) return true;
92 }
93 return false;
94 }
95
96 void agument()
97 {
98 int now,next,stop;
99 long long delta;
100 for (int a=s;a<=e;a++)
101 p[a]=v[a];
102 stack[stop=1]=s;
103 while (stop>0)
104 {
105 now=stack[stop];
106 if (now!=e)
107 {
108 for (;p[now];p[now]=p[now]->next)
109 if ((p[now]->f) && (d[now]+1==d[next=p[now]->e])) break;
110 if (p[now])
111 {
112 stack[++stop]=next;
113 fe[stop]=p[now];
114 }
115 else
116 {
117 stop--;
118 d[now]=-1;
119 }
120 }
121 else
122 {
123 delta=INF;
124 for (int a=stop;a>=2;a--)
125 if (fe[a]->f<delta) delta=fe[a]->f;
126 ans+=delta;
127 for (int a=stop;a>=2;a--)
128 {
129 fe[a]->f-=delta;
130 fe[a]->op->f+=delta;
131 if (fe[a]->f==0) stop=a-1;
132 }
133 }
134 }
135 }
136
137
138 void dinic()
139 {
140 while (bfs())
141 agument();
142 }
143
144 int main()
145 {
146 freopen("milk6.in","r",stdin);
147 freopen("milk6.out","w",stdout);
148
149 scanf("%d%d",&n,&m);
150 for (int a=1;a<=m;a++)
151 {
152 int s,e;
153 long long v;
154 scanf("%d%d%lld",&s,&e,&v);
155 l++;
156 x[l]=s;y[l]=e;z[l]=v;
157 add_edge(s,e,v*1001+1);
158 }
159 s=1;e=n;
160 dinic();
161 printf("%lld %lld\n",ans / 1001,ans % 1001);
162 if (ans % 1001==0)
163 {
164 return 0;
165 }
166 int cnt=0;
167 for (int a=1;a<=m;a++)
168 if (!use[a])
169 {
170 if (ans % 1001-cnt==0) break;
171 en=0;
172 memset(v,0,sizeof(v));
173 for (int b=1;b<=m;b++)
174 if (x[a]!=x[b] || y[a]!=y[b]) add_edge2(x[b],y[b]);
175 memset(use2,false,sizeof(use2));
176 bool able=!dfs3(s);
177 if (able)
178 {
179 int nowv=0;
180 for (int b=1;b<=m;b++)
181 if (x[b]==x[a] && y[b]==y[a])
182 {
183 use[b]=true;
184 cnt++;
185 nowv+=z[b];
186 }
187 if (nowv!=ans/1001)
188 {
189 cnt=0;
190 for (int b=1;b<=m;b++)
191 if (x[b]==x[a] && y[b]==y[a]) use[b]=false;
192 continue;
193 }
194 break;
195 }
196 }
197 en=0;
198 memset(v,0,sizeof(v));
199 for (int b=1;b<=m;b++)
200 if (!use[b]) add_edge(x[b],y[b],z[b]);
201 int nowcnt=ans%1001-cnt;
202 ans=0;
203 dinic();
204 for (int a=1;a<=m;a++)
205 {
206 en=0;
207 memset(v,0,sizeof(v));
208 for (int b=1;b<=m;b++)
209 if (!use[b] && b!=a) add_edge(x[b],y[b],z[b]);
210 long long nowans=ans;
211 ans=0;
212 dinic();
213 if (nowans-ans==z[a])
214 {
215 ans+=z[a];
216 for (int b=1;b<=m;b++)
217 if (x[b]==x[a] && y[b]==y[a])
218 {
219 use[b]=true;
220 nowcnt--;
221 ans-=z[b];
222 }
223 if (nowcnt==0) break;
224 }
225 else ans=nowans;
226 }
227 for (int a=1;a<=m;a++)
228 if (use[a]) printf("%d\n",a);
229
230 return 0;
231 }