USACO 4.4.2 milk6

题目:

http://ace.delos.com/usacoprob2?a=H4mXhbyi4yi&S=milk6

http://www.nocow.cn/index.php/Translate:USACO/milk6

 

Pollutant Control
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位整数。

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

 

 

转载于:https://www.cnblogs.com/zhonghaoxi/archive/2012/07/02/2573715.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值