【CF#241E】Flights 差分约束

AC通道:http://codeforces.com/problemset/problem/241/E

【题目大意】

给定一幅n个节点m条边的无重边的DAG,所有边都从编号小的节点指向编号大的节点,且从节点1出发能到达n.

现要求给每条边分配边权1或2,使得从节点1到n的任意路径长度均相等,判定无解或输出任意方案.

2≤n≤1000,1≤m≤5000.

【题解】

对于给定的点(x,y),它们要满足条件1<=dis[y]-dis[x]<=2

变形得到dis[y]<=dis[x]+2,dis[x]<=dis[y]-1

然后通过dfs标记图中不在从1到n的路径的点

然后就是差分约束的那一套了。

/*************
  CF #241E
  by chty
  2016.11.16
*************/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 1010
#define up(i,j,n) for(ll i=j;i<=n;i++)
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline ll read(){
		ll x=0,f=1;  char ch=getc();
		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
		return x*f;
	}
}using namespace INIT;
struct node{ll y,next,v;}e[5010*2];
ll n,m,len,X[5010],Y[5010],Link[MAXN],check[MAXN],vis[MAXN],dis[MAXN],T[MAXN];
void insert(ll x,ll y,ll v) {e[++len].next=Link[x];Link[x]=len;e[len].y=y;e[len].v=v;}
void dfs(ll x){
	vis[x]=1;
	if(x==n) {check[x]=1; return;}
	for(ll i=Link[x];i;i=e[i].next){
		if(e[i].v<0)  continue;
		if(!vis[e[i].y])  dfs(e[i].y);
		if(check[e[i].y])  check[x]=1;
	}
}
void spfa(){
	memset(vis,0,sizeof(vis));
	memset(dis,127,sizeof(dis));
	queueq;
	q.push(1); vis[1]=1; dis[1]=0;
	while(!q.empty()){
		ll x=q.front();  q.pop();
		for(ll i=Link[x];i;i=e[i].next){
			if(!check[e[i].y])  continue;
			if(dis[x]+e[i].vn)  {puts("No");return;}
					q.push(e[i].y);
					vis[e[i].y]=1;
					T[e[i].y]++;
				}
			}
		}
		vis[x]=0;
	}
	puts("Yes");
	up(i,1,m) {
		if(dis[Y[i]]-dis[X[i]]==1)  puts("1");
		else puts("2");
	}
}
int main(){
	//freopen(FILE".in","r",stdin);
	//freopen(FILE".out","w",stdout);
	n=read();  m=read();
	up(i,1,m)  {X[i]=read(); Y[i]=read(); insert(X[i],Y[i],2); insert(Y[i],X[i],-1);}
	dfs(1);
	spfa();
	return 0;
}


你可能感兴趣的:(差分约束,codeforces)