您的位置:首页 > 其它

hdu 5385 The path 贪心?构造

2015-08-17 08:28 435 查看


The path

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 607 Accepted Submission(s): 236

Special Judge


Problem Description

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 ∈ [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, 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



Output

For each test case,print m lines.The
i-th line includes one integer:the length of edge from ui to vi



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




Author

SXYZ



Source

2015 Multi-University Training Contest 8



Recommend

wange2014


d(1)<d(2)<....d(x)>d(x+1)>...d(n),那么所有点的d()可以分为两部分呢,一部分是从的d[1]开始,从小到大,一部分从d
开始从小到大
,也可能从d[1]开始从小到大直到d

因为一定有解,从1开始,一步之内一定有路径通往2或n,然后2一定有路径通往3或n,(如果n可达)n一定有路径通往n-1或前面的。
以这个为顺序表明d(),比如说d[1]标为1,那么如果到了d[2],标为2,如果d[2]不能到3只能到n,那么d
=3,n绝对可以到3或n-1中的一个
,标为4,直到把所有点的dis[]标完,两头向中间夹。
ps:如果现在为点2,(且dis[2]已标为2,dis[1]标为了1),点2出发可以到3和5,那么下一个拓展3,把3标为3,而不是拓展5,下一个准备标记dis[]的是4或n,
这两个至少一个可以通过现在的点到达。
标记完后,因为之前用vis,记录了某些点访问过没,我们标记时走过的边长度为边上两点dis[]之差,还有些没有走过的边,
直接标为n(最大长度),不然可能会破坏我们设计好的dis[]顺序性。
比如说:左边从1到x,右边从n到x,标记完了。
现在x的dis[]最大,从3到x有条边,但是到3之后没有选择标x,而是选择标其他的,然后通过其他的路到x,这个时候如果把这条边随便标为1、2、3之类的
可能dis[x]就比其他一些dis[]小了(本应最大)。(按照我们的标法,最大dis[]为n,所以这条边标为n就可以认为是无穷,就相当于没有从3到x的路径)

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
#include<utility>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI 3.1415926535897932384626
#define eps 1e-10
#define sqr(x) ((x)*(x))
#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)
#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)
#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)
#define  lson   num<<1,le,mid
#define rson    num<<1|1,mid+1,ri
#define MID   int mid=(le+ri)>>1
#define zero(x)((x>0? x:-x)<1e-15)

using namespace std;
const int INF =0x3f3f3f3f;
const int maxn=100000+10    ;
const int maxm=100000+10    ;
//const int INF=    ;
typedef long long ll;
const ll inf =1000000000000000;//1e15;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
//by yskysker123
int n,m;
bool incl[maxm];
int u[maxm],v[maxm],nex[maxm];
int fir[maxn];
bool vis[maxn];
int d[maxn];
int e_max;
inline void add_edge(int s,int t)
{
    int e=e_max++;
    u[e]=s;
    v[e]=t;
    nex[e]=fir[s];
    fir[s]=e;
}
void init()
{
    e_max=0;
    memset(fir,-1,sizeof fir);
    memset(vis, 0,sizeof vis);
    memset(incl,0,sizeof incl);

}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int x,y;
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            add_edge(x,y);

        }
        int le=1,ri=n,t=0;
        vis[1]=1;
        while(le<=ri)
        {

            if( vis[le] )
            {
                d[le]=++t;
                for(int e=fir[le];~e;e=nex[e])
                {

                    int y=v[e];
                    if(vis[y])  continue;
                    vis[y]=1;
                    incl[e]=1;

                }
                le++;
            }
            if(vis[ri])
            {
                d[ri]=++t;
                for(int e=fir[ri];~e;e=nex[e])
                {
                    int y=v[e];
                    if(vis[y])  continue;
                    vis[y]=1;
                    incl[e]=1;
                }
                ri--;
            }

        }
        for(int e=0;e<m;e++)
        {
            if(incl[e])
            {
                int x=u[e];
                int y=v[e];

                  printf("%d\n",abs(d[x]-d[y]));
            }
            else
            {
                printf("%d\n",n);
            }

        }
    }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: