您的位置:首页 > 其它

UVa 10480 Sabotage ( 最小割最大流定理)

2018-01-11 11:16 597 查看
The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebellion.

Because of the enormous disturbances this is causing in world economy, an imperialist military

super power has decided to invade the country and reinstall the old regime.

For this operation to be successful, communication between the capital and the largest city must

be completely cut. This is a difficult task, since all cities in the country are connected by a computer

network using the Internet Protocol, which allows messages to take any path through the network.

Because of this, the network must be completely split in two parts, with the capital in one part and

the largest city in the other, and with no connections between the parts.

There are large differences in the costs of sabotaging different connections, since some are much

more easy to get to than others.

Write a program that, given a network specification and the costs of sabotaging each connection,

determines which connections to cut in order to separate the capital and the largest city to the lowest

possible cost.

Input

Input file contains several sets of input. The description of each set is given below.

The first line of each set has two integers, separated by a space: First one the number of cities, n in

the network, which is at most 50. The second one is the total number of connections, m, at most 500.

The following m lines specify the connections. Each line has three parts separated by spaces: The

first two are the cities tied together by that connection (numbers in the range 1 − n). Then follows the

cost of cutting the connection (an integer in the range 1 to 40000000). Each pair of cites can appear

at most once in this list.

Input is terminated by a case where values of n and m are zero. This case should not be processed.

For every input set the capital is city number 1, and the largest city is number 2.

Output

For each set of input you should produce several lines of output. The description of output for each set

of input is given below:

The output for each set should be the pairs of cities (i.e. numbers) between which the connection

should be cut (in any order), each pair on one line with the numbers separated by a space. If there is

more than one solution, any one of them will do.

Print a blank line after the output for each set of input.

Sample Input

5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

0 0

Sample Output

4 1

3 4

3 5

3 2

4 1

3 4

3 5

3 2

题意:一个国家出了内乱,现在想要把首都和最大的城市的通讯完全断开,但是断开一条边有花费,现在问断开哪些边可以使花费最小。

分析:跑一遍最大流dinic后,根据最小割定理,整部图被分为S,T两部分,从源点出发dfs得到S集的点,剩下的为T集的点,然后输出左右两边各一个连着的点就是割边。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod=609929123;
const int N=100220;
int n,f,d,m;
int S,T,R;//源点,汇点
struct node
{
int v,cap,next;//领接表
}es[4*N];
int frist
;
int dis
;
int current
;//当前弧优化
int x
,y
;
int vis
;
int addedge(int u,int v,int cap)
{
node e1={v,cap,frist[u]};
es[R]=e1;
frist[u]=R++;
}
int bfs()
{
queue<int>q;
q.push(S);
memset(dis,-1,sizeof(dis));
dis[S]=0;
while(!q.empty())
{
int h=q.front();
if(h==T) return 1;
q.pop();
for(int i=frist[h];i!=-1;i=es[i].next)
{
int temp=es[i].v;
if(dis[temp]==-1&&es[i].cap)
{
dis[temp]=dis[h]+1;
q.push(temp);
}
}
}
return 0;
}
int dinic(int x,int maxflow)
{
if(x==T) return maxflow;
int flow,f=0;
for(int &i=current[x];i!=-1;i=es[i].next)
{
int temp=es[i].v;
if(dis[temp]==dis[x]+1&&es[i].cap)
{
flow=dinic(temp,min(maxflow-f,es[i].cap));
es[i].cap-=flow;
es[i^1].cap+=flow;
f+=flow;
if(f==maxflow) break;
}
}
return f;
}
int DINIC()
{
int ans=0;
while(bfs())
{
int flow;
memcpy(current,&frist,sizeof(frist));
while(flow=dinic(S,inf))
ans+=flow;
}
return ans;
}
void dfs(int x)//最小割 找出s部分的点
{
vis[x]=1;
for(int i=frist[x];i!=-1;i=es[i].next)
{
int temp=es[i].v;
if(!vis[temp]&&es[i].cap)
dfs(temp);
}
}
int main()
{
int u,v,cap;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
memset(frist,-1,sizeof(frist));
R=0,S=1,T=2;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x[i],&y[i],&cap);
addedge(x[i],y[i],cap);
addedge(y[i],x[i],cap);
}
DINIC();
memset(vis,0,sizeof(vis));
dfs(S);
for(int i=1;i<=m;i++)
{
if((vis[x[i]]&&!vis[y[i]])||(vis[y[i]]&&!vis[x[i]]))
printf("%d %d\n",x[i],y[i]);
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: