hdu 5385 The path

  
  
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   (1ui,vin) , indicating there is a link between nodes  ui  and  vi  and the direction is from  ui  to  vi . n3105 , m6105 1n,m105
 

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




#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;
}

1006.The path

如果我们知道每个点的disdis值和最短路径树的话,方案是很容易构造的

我们可以采取贪心做法,一开始将11号点作为最短路径树的根,然后左边从22开始,右边从nn开始,只要之前加入的点有边连向他们就加入

这样一个点加入的时间就是他的disdis值,最短路径树上的父亲也可以确定,于是输出时非树边长度为nn,树边长度为两个端点disdis之差

刚开始看成无向图,WA了半天

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值