1. 程式人生 > >Internship-ZOJ2532(網路流求割邊)

Internship-ZOJ2532(網路流求割邊)

Internship
Time Limit: 5 Seconds      Memory Limit: 32768 KB

CIA headquarter collects data from across the country through its classified network. They have been usingoptical fibres long before it's been deployed on any civilian projects. However they are still under a lotpressure recently because the data are growing rapidly. As a result they are considering upgrading thenetwork with new technologies that provide a few times wider bandwidth. In the experiemental stage,they would like to upgrade one segment of their original network in order to see how it performs. Andas a CIA intern it's your responsibility to investigate which segment could actually help increasethe total bandwidth the headquarter receives, suppose that all the cities have infinite data to sendand the routing algorithm is optimized. As they have prepared the data for you in a few minutes, you aretold that they need the result immediately. Well, practically immediately.

Input

Input contains multiple test cases. First line of each test case contains three integers n, m and l, theyrepresent the number of cities, the number of relay stations and the number of segments. Cities will bereferred to as integers from 1 to n, while relay stations use integers from n+1 to n+m. You can savesassume that n + m <= 100, l <= 1000 (all of them are positive). The headquarter is identified by theinteger 0.

The next l lines hold a segment on each line in the form of a b c, where a is the source node and b isthe target node, while c is its bandwidth. They are all integers where a and b are valid identifiers(from 0 to n+m). c is positive. For some reason the data links are all directional.

The input is terminated by a test case with n = 0. You can safely assume that your calculation canbe housed within 32-bit integers.

Output

For each test print the segment id's that meets the criteria. The result is printed in a single lineand sorted in ascending order, with a single space as the separator. If none of the segment meets thecriteria, just print an empty line. The segment id is 1 based not 0 based.

Sample Input
2 1 3
1 3 2
3 0 1
2 0 1
2 1 3
1 3 1
2 3 1
3 0 2
0 0 0
Sample Output
2 3
<hey here is an invisible empty line>

Author: WU, Jiazhi

Source: CYJJ's Funny Contest #3, Having Fun in Summer

題意:CIA公司想採用新技術升級網路,在實驗測試階段,他們想升級其中的一段網路以便觀察新技術在多大的長度上提升網路的效能,你作為實習生的任務是調查那一段網路能提高CIA總部的寬頻。

思路:判斷一段網路可不可以提升網路就要看它是不是滿流,如果滿流則可能在升級後提升CIA總部的寬頻,但是如果提升後並不能增廣,即不能提升CIA總部的寬頻,所以判斷一段是不是可提升的則有兩個條件:(1)在進行增廣後這段網路是滿流的,(2)在提升後可以增廣。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;

typedef struct node
{
	
	int u;

	int v;
	
	int Flow;

	int next;
}Line;

Line Li[2200];

int Head[110],top;

int vis[110],ans[110];

bool vis1[110],vis2[110];

int n,m,l;

int s,t;

void AddEdge(int u,int v,int f)
{
	Li[top].v=v; Li[top].u=u;
	Li[top].Flow=f;
	Li[top].next=Head[u];
	Head[u]=top++;
}

bool BFS()
{
	memset(vis,-1,sizeof(vis));

	vis[s]=0;

	queue<int >Q;
	
	Q.push(s);

	while(!Q.empty())
	{
		
		int u=Q.front();
		
		Q.pop();

		for(int i=Head[u];i!=-1;i=Li[i].next)
		{

			if(Li[i].Flow&&vis[Li[i].v]==-1)
			{
				vis[Li[i].v]=vis[u]+1;

				Q.push(Li[i].v);

			}
		}
	}
	return vis[t]!=-1;

}

int DFS(int u,int f)
{
	if(u==t)
	{
		return f;
	}
	int ans=0;

	for(int i=Head[u];i!=-1;i=Li[i].next)
	{
		if(Li[i].Flow&&vis[Li[i].v]==vis[u]+1)
		{
			int d=DFS(Li[i].v,min(f,Li[i].Flow));
			f-=d;
			Li[i].Flow-=d;
			Li[i^1].Flow+=d;
			ans+=d;
		}
	}
	return ans;
}

void dfs(int u,bool *vist,int op)
{
	vist[u]=true;


	for(int i=Head[u];i!=-1;i=Li[i].next)
	{
		if(!vist[Li[i].v]&&Li[i^op].Flow!=0)
		{
			dfs(Li[i].v,vist,op);
		}
	}
}

void Dinic()//網路流進行增廣
{
	int ans;

	while(BFS())
	{
		ans=DFS(s,INF);

	}
}



int main()
{
	while(~scanf("%d %d %d",&n,&m,&l))
	{

		if(n+m+l==0)
		{
			break;
		}
		
		s=n+m+1;//源點
		
		t=0;//匯點

		memset(Head,-1,sizeof(Head));

		int a,b,c;
		
		top = 0;

		for(int i=0;i<l;i++)
		{
			scanf("%d %d %d",&a,&b,&c);
			AddEdge(a,b,c);//建立邊,正向為c,負向為0
			AddEdge(b,a,0);
		}

		for(int i=1;i<=n;i++)
		{
			AddEdge(s,i,INF);

			AddEdge(i,s,0);//建立城市與源點之間的邊,權值為INF
		}
		
		Dinic();

		memset(vis1,false,sizeof(vis1));

		memset(vis2,false,sizeof(vis2));

		dfs(s,vis1,0);//從源點向匯點搜尋,標記還有剩餘流的點

		dfs(t,vis2,1);//從匯點到源點搜尋,標記還有剩餘流的點
	
		int num=0;

		for(int i=0;i<l;i++)
		{
			if(Li[i<<1].Flow==0&&vis1[Li[i<<1].u]&&vis2[Li[i<<1].v])
			{
				ans[num++]=i+1;//如果一條邊的u與v都被標記,表明s->u,v->t,但是這條邊是滿流,所以提升這條邊。
			}
		}

		if(num)
		{
			for(int i=0;i<num;i++)
			{
				if(i)
				{
					printf(" ");
				}
				printf("%d",ans[i]);
			}
		}
		printf("\n");

	}
	return 0;
}