1. 程式人生 > >【BZOJ2095】[Poi2010]Bridges 動態加邊網絡流

【BZOJ2095】[Poi2010]Bridges 動態加邊網絡流

mage ems output string get 之間 一行 ++ cpp

【BZOJ2095】[Poi2010]Bridges

Description

YYD為了減肥,他來到了瘦海,這是一個巨大的海,海中有n個小島,小島之間有m座橋連接,兩個小島之間不會有兩座橋,並且從一個小島可以到另外任意一個小島。現在YYD想騎單車從小島1出發,騎過每一座橋,到達每一個小島,然後回到小島1。霸中同學為了讓YYD減肥成功,召喚了大風,由於是海上,風變得十分大,經過每一座橋都有不可避免的風阻礙YYD,YYD十分ddt,於是用泡芙賄賂了你,希望你能幫他找出一條承受的最大風力最小的路線。

Input

輸入:第一行為兩個用空格隔開的整數n(2<=n<=1000),m(1<=m<=2000),接下來讀入m行由空格隔開的4個整數a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座橋連接小島a和b,從a到b承受的風力為c,從b到a承受的風力為d。

Output

輸出:如果無法完成減肥計劃,則輸出NIE,否則第一行輸出承受風力的最大值(要使它最小)

Sample Input

4 4
1 2 2 4
2 3 3 4
3 4 4 4
4 1 5 4
技術分享

Sample Output

4

題解:混合圖歐拉回路做法:先將所有邊隨意定向,然後從S向所有度數為正的點連邊,度數為負的點向T連邊,再連上原圖的反向邊,跑最大流看是否有解即可。

對於本題,我們可以先對於每條邊選取阻力較小的那個方向,然後將按另一個方向的阻力排序,從小到大扔到圖中,如果扔進去之後滿流了,則輸出答案即可。

網上部分用二分做的代碼有問題,可以被hack。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,ans,sum,cnt,S,T;
struct node
{
	int a,b,c,d;
}p[2010];
int to[10010],next[10010],val[10010],head[1010],d[1010];
queue<int> q;
bool cmp(const node &a,const node &b)
{
	return a.d<b.d;
}
inline void add(int a,int b,int c)
{
	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
	to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
}
int dfs(int x,int mf)
{
	if(x==T)	return mf;
	int i,k,temp=mf;
	for(i=head[x];i!=-1;i=next[i])	if(d[to[i]]==d[x]+1&&val[i])
	{
		k=dfs(to[i],min(temp,val[i]));
		if(!k)	d[to[i]]=0;
		val[i]-=k,val[i^1]+=k,temp-=k;
		if(!temp)	break;
	}
	return mf-temp;
}
int bfs()
{
	memset(d,0,sizeof(d));
	while(!q.empty())	q.pop();
	int i,u;
	q.push(S),d[S]=1;
	while(!q.empty())
	{
		u=q.front(),q.pop();
		for(i=head[u];i!=-1;i=next[i])	if(!d[to[i]]&&val[i])
		{
			d[to[i]]=d[u]+1;
			if(to[i]==T)	return 1;
			q.push(to[i]);
		}
	}
	return 0;
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)	f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+(gc^‘0‘),gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd();
	int i;
	for(i=1;i<=m;i++)
	{
		p[i].a=rd(),p[i].b=rd(),p[i].c=rd(),p[i].d=rd();
		if(p[i].c>p[i].d)	swap(p[i].a,p[i].b),swap(p[i].c,p[i].d);
		d[p[i].a]++,d[p[i].b]--;
		ans=max(ans,p[i].c);
	}
	sort(p+1,p+m+1,cmp);
	memset(head,-1,sizeof(head));
	S=0,T=n+1;
	for(i=1;i<=n;i++)
	{
		if(d[i]&1)
		{
			printf("NIE");
			return 0;
		}
		d[i]>>=1;
		if(d[i]>0)	add(S,i,d[i]),sum+=d[i];
		if(d[i]<0)	add(i,T,-d[i]);
	}
	if(sum)	for(i=1;i<=m;i++)
	{
		add(p[i].a,p[i].b,1);
		ans=max(ans,p[i].d);
		while(bfs())	sum-=dfs(S,1<<30);
		if(!sum)	break;
	}
	if(sum)	printf("NIE");
	else	printf("%d",ans);
	return 0;
}

【BZOJ2095】[Poi2010]Bridges 動態加邊網絡流