Live2D

题解 CF241E Flights

题目传送门

题目大意

给出一个 \(n\) 个点 \(m\) 条边的 \(\texttt{DAG}\) ,给每条边设定边权为 \(1\) 或者 \(2\) ,使得 \(1\to n\) 的每条路径长度都相同。

\(n\le 10^3,m\le 5\times 10^3\)

思路

老实说,真的对得起 \(2600\) 的评分(以我现在的角度来看),正解应该算比较难想的吧。。。

首先肯定需要把没有用的路径删掉,就是不能从 \(1\to n\) 的路径。

首先我们会发现一个比较显然的结论:\(1\to i\) 的任意路径都应该相同。这个结论应该都能想到,但是应该怎么用呢?如果我们设 \(\text{dis}(i)\) 表示 \(1\to i\) 的最短路径长度,那么如果存在边 \(u\to v\),则有:

\[\text{dis}(u)+1\le \text{dis}(v)\le \text{dis}(u)+2 \]

然后我们发现这个东西我们可以用差分约束解决。时间复杂度则为 \(\texttt{SPFA}\) 的时间复杂度。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define PII pair<int,int>
#define Int register int
#define MAXM 5005
#define MAXN 1005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int n,m;
PII Edge[MAXM];
int toop = 1,to[MAXM << 1],nxt[MAXM << 1],wei[MAXM << 1],tim[MAXN],vis[MAXN],dis[MAXN],head[MAXN];

void Add_Edge (int u,int v,int w){
//	cout << u << " -> " << v << ": " << w << endl;
	to[++ toop] = v,wei[toop] = w,nxt[toop] = head[u],head[u] = toop;
}

void Spfa (){
	queue <int> q;
	while (!q.empty()) q.pop ();
	memset (vis,0,sizeof (vis));
	memset (dis,0x3f,sizeof (dis));
	q.push (1),vis[1] = 1,dis[1] = 0;
	while (!q.empty()){
		int u = q.front();q.pop ();vis[u] = 0,tim[u] ++;
		if (tim[u] > n){
			puts ("No");
			exit (0);
		}
		for (Int i = head[u];i;i = nxt[i]){
			int v = to[i],w = wei[i];
			if (dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;
				if (!vis[v]) vis[v] = 1,q.push (v);
			}
		}
	}
}

vector <int> G[2][MAXN];
int ans[MAXN],vis1[MAXN];

void dfs (int u,int ty){vis1[u] |= 1 << ty;for (int v : G[ty][u]) if (!(vis1[v] & (1 << ty)))dfs (v,ty);}

signed main(){
	read (n,m);
	for (Int i = 1,u,v;i <= m;++ i) read (u,v),Edge[i] = make_pair (u,v),G[0][u].push_back (v),G[1][v].push_back (u);
	dfs (1,0),dfs (n,1);for (Int i = 1,u,v;i <= m;++ i){
		u = Edge[i].first,v = Edge[i].second;
		if (vis1[u] == 3 && vis1[v] == 3) Add_Edge (u,v,2),Add_Edge (v,u,-1);
	}
	Spfa ();
	puts ("Yes");
	for (Int i = 1;i <= m;++ i){
		int u = Edge[i].first,v = Edge[i].second;
		if (vis1[u] == 3 && vis1[v] == 3) write (dis[v] - dis[u]),putchar ('\n');
		else puts ("1");
	}
 	return 0;
}
posted @ 2020-08-21 16:08  Dark_Romance  阅读(107)  评论(0编辑  收藏  举报