Problem DescriptionYou have a connected directed graph.Let d(x) be the length of the shortest path from 1 to x .Specially d(1)=0 .A graph is good if there exist x satisfy d(1)<d(2)<....d(x)>d(x+1)>...d(n) .Now you need to set the length of every edge satisfy that the graph is good.Specially,if d(1)<d(2)<..d(n) ,the graph is good too. The length of one edge must ∈ [1,n] It's guaranteed that there exists solution.
InputThere are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case: The first line contains two integers n and m,the number of vertexs and the number of edges.Next m lines contain two integers each, ui and vi (1≤ui,vi≤n) , indicating there is a link between nodes ui and vi and the direction is from ui to vi . ∑n≤3∗105 , ∑m≤6∗105 1≤n,m≤105
OutputFor each test case,print m lines.The i-th line includes one integer:the length of edge from ui to vi
Sample Input2 4 6 1 2 2 4 1 3 1 2 2 2 2 3 4 6 1 2 2 3 1 4 2 1 2 1 2 1
Sample Output1 2 2 1 4 4 1 1 3 4 4 4
#include <iostream> #include<vector> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int mx=500000; int T,n,m; struct edge { int to,id; }; vector<edge> g[mx]; int used[mx],id[mx]; struct EG { int u,v,dis; } eg[mx]; void init() { for(int i=0;i<=n;i++) g[i].clear(); } void add_edge(int u,int v,int id) { g[u].push_back(edge{v,id}); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); add_edge( u, v,i); eg[i].u=u;eg[i].v=v;eg[i].dis=n; } queue<int> que; vector<int> ans; que.push(1);memset(used,0,sizeof(used));used[1]=1; int tar1=2,tar2=n; while(!que.empty()) { int u=que.front();ans.push_back(u);que.pop(); for(int i=0;i<g[u].size();i++) { int v=g[u][i].to; if(!used[v]) used[v]=g[u][i].id; } while(tar1<=tar2&&used[tar1]) {que.push(tar1);tar1++;} while(tar2>=tar1&&used[tar2]) {que.push(tar2);tar2--;} } for(int i=0;i<ans.size();i++) { id[ans[i]]=i; } for(int i=2;i<=n;i++) { EG &t=eg[used[i]]; t.dis=abs(id[t.u]-id[t.v] ); } for(int i=1;i<=m;i++) { printf("%d\n",eg[i].dis); } } return 0; }
如果我们知道每个点的dis值和最短路径树的话,方案是很容易构造的
我们可以采取贪心做法,一开始将1号点作为最短路径树的根,然后左边从2开始,右边从n开始,只要之前加入的点有边连向他们就加入
这样一个点加入的时间就是他的dis值,最短路径树上的父亲也可以确定,于是输出时非树边长度为n,树边长度为两个端点dis之差
刚开始看成无向图,WA了半天
hdu 5385 The path
最新推荐文章于 2020-12-09 10:16:05 发布