[CF241E]Flights

[CF241E]Flights

题目大意:

给一张\(n(n\le1000)\)个点\(m(m\le5000)\)条边的DAG,确定每条边的边权\(w_i(w_i\in\{1,2\})\),使得所有从\(1\)\(n\)的路径拥有相同的长度。

思路:

首先用BFS求出所有与\(1\)\(n\)路径有关的点构成的子图。

这样,\(1\)到子图上每个点的长度都是确定的,即终点相同的路径拥有相同的长度。有\(d_i\)表示点\(1\)到点\(i\)的距离,则对于边\(u\to v\),有\(1\le d_v-d_u\le2\)。这样我们就可以得到一个差分约束系统,使用SPFA求最长路即可。

源代码:

#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=1001,M=5000;
struct Edge {
	int u,v;
};
Edge edge[M];
std::vector<int> e[N];
std::vector<Edge> h[N];
int n,m,vis[N],dis[N];
bool f[N],g[N],inq[N];
std::queue<int> q;
inline void bfs1() {
	for(register int i=0;i<m;i++) {
		e[edge[i].u].push_back(edge[i].v);
	}
	q.push(1);
	f[1]=true;
	while(!q.empty()) {
		const int &x=q.front();
		for(auto &y:e[x]) {
			if(!f[y]) {
				q.push(y);
				f[y]=true;
			}
		}
		q.pop();
	}
	for(register int i=1;i<=n;i++) {
		e[i].clear();
	}
}
inline void bfs2() {
	for(register int i=0;i<m;i++) {
		e[edge[i].v].push_back(edge[i].u);
	}
	q.push(n);
	g[n]=true;
	while(!q.empty()) {
		const int &x=q.front();
		for(auto &y:e[x]) {
			if(!g[y]) {
				q.push(y);
				g[y]=true;
			}
		}
		q.pop();
	}
	for(register int i=1;i<=n;i++) {
		e[i].clear();
	}
}
inline void spfa() {
	q.push(1);
	while(!q.empty()) {
		const int &x=q.front();
		for(auto &j:h[x]) {
			const int &y=j.u,&w=j.v;
			if(dis[x]+w>dis[y]) {
				dis[y]=dis[x]+w;
				if(!inq[y]) {
					inq[y]=true;
					q.push(y);
					if(++vis[y]>n) {
						throw 0;
					}
				}
			}
		}
		q.pop();
		inq[x]=false;
	}
}
int main() {
	n=getint(),m=getint();
	for(register int i=0;i<m;i++) {
		const int u=getint(),v=getint();
		edge[i]=(Edge){u,v};
	}
	bfs1();
	bfs2();
	for(register int i=0;i<m;i++) {
		const int &u=edge[i].u,&v=edge[i].v;
		if(f[u]&&g[u]&&f[v]&&g[v]) {
			h[u].push_back((Edge){v,1});
			h[v].push_back((Edge){u,-2});
		}
	}
	try {
		spfa();
	} catch(...) {
		puts("No");
		return 0;
	}
	puts("Yes");
	for(register int i=0;i<m;i++) {
		const int &u=edge[i].u,&v=edge[i].v;
		if(f[u]&&g[u]&&f[v]&&g[v]) {
			printf("%d\n",dis[v]-dis[u]);
		} else {
			puts("1");
		}
	}
	return 0;
}
posted @ 2018-09-28 14:16  skylee03  阅读(244)  评论(0编辑  收藏  举报