HDOJ 5385 The path
Dicription
You 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 $\in$ $[1,n]$
It's guaranteed that there exists solution.
The length of one edge must $\in$ $[1,n]$
It's guaranteed that there exists solution.
Input
There 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, $u_i$ and $v_i$ $(1 \leq u_i,v_i \leq n)$, indicating there is a link between nodes $u_i$ and $v_i$ and the direction is from $u_i$ to $v_i$.
$\sum n \leq 3*10^5$,$\sum m \leq 6*10^5$
$1\leq n,m \leq 10^5$
Output
For each test case,print $m$ lines.The i-th line includes one integer:the length of edge from $u_i$ to $v_i$
Sample Input
2 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 Output
1 2 2 1 4 4 1 1 3 4 4 4
一开始只有d[1]是已知的且为0,那么我们不妨维护一个区间[l,r],区间内的位置的d值都是未知的,区间外的d值都是已知的且满足任意一个
区间外的d值都小于区间内的d值。
我们让区间不断缩小,最后就可以得到题目要求的玩意了。
问题是怎么缩小??
反正本题是SPJ只要你得到一个合法解就行了。
而且还有一个很重要的性质是,l或r肯定是[l,r]里d值最小的,所以我们每次只需要把l或者r扩展成已知的然后让l++或者r--就行了的。
假如要扩展l吧,那么首先区间内连向它的边是没有用的,因为本来d值就肯定比它大了,不可能影响最短路;
而区间外的任意一点x连向它的边都至少是d[l]-d[x]且至少有一个是d[l]-d[x],又因为边权有上界限制,所以我们让d[l]为区间外最大的
d值+1即可,这样最大的d也只是n,不会出事。
然后就可以A题了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define maxn 100005 using namespace std; int to[maxn],ne[maxn],hd[maxn]; int num,n,m,l,r,val[maxn],d[maxn]; int now,T; inline void init(){ for(int i=1;i<=n;i++) hd[i]=0; for(int i=1;i<=m;i++) val[i]=0; num=0; } inline bool check(int pos){ for(int i=hd[pos];i;i=ne[i]) if(to[i]<l||to[i]>r){ now++,d[pos]=now; for(;i;i=ne[i]) if(to[i]<l||to[i]>r){ val[i]=now-d[to[i]]; } return 1; } return 0; } inline void solve(){ d[1]=now=0; l=2,r=n; while(l<=r){ if(check(l)) l++; else check(r),r--; } } int main(){ scanf("%d",&T); while(T--){ init(); int uu,vv; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&uu,&vv); to[++num]=uu,ne[num]=hd[vv],hd[vv]=num; } solve(); for(int i=1;i<=m;i++){ if(!val[i]) val[i]=n; printf("%d\n",val[i]); } } return 0; }
我爱学习,学习使我快乐