Hdu 5385 The path

题目链接:

  Hdu 5385 The path

题目描述:

  给出一个有向图,有n个点,m条边。假设从1到x点的最短路的值用d(x),要求给每条边赋一个[1,n]边权值后,存在一个y属于[1,n]使得:d(1)<d(2)<d(3)...d(y-1)<d(y)>d(y+1)...d(n-1)>d(n),输出任意一种赋值方案。

解题思路:

  因为分配好边权以后要满足这个式子:d(1)<d(2)<d(3)...d(y-1)<d(y)>d(y+1)...d(n-1)>d(n)。又因为在用prim求最小生成树的时候,向生成树上加点的顺序就满足:最先加入的点到树根的距离最短。然后我们就根据这个性质每次向生成树上加点就好了。每次加点要么加编号最小的,要么加编号最大的,并且记录加入时间,最后在生成树上的边权值为两端点加入时间之差,不在生成树上的边权值记为n即可。

  比赛的时候感觉这个题目炒鸡高大上,想到套用各种算法,看了题解感觉自己蠢哭了好嘛?现在写题解呢,我竟然不知道要把这个题目分类到哪里合适了。

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 100005;
 9 struct node
10 {
11     int to, next, id;
12 } edge[maxn];
13 
14 struct Node
15 {
16     int l, r;
17 } p[maxn];
18 int tot, head[maxn], dis[maxn];
19 bool vis[maxn], ans[maxn];
20 
21 void init ()
22 {
23     tot = 0;
24     memset (head, -1, sizeof(head));
25     memset (ans, false, sizeof(ans));
26     memset (dis, 0, sizeof(dis));
27     memset (vis, false, sizeof(vis));
28 }
29 
30 void Add (int from, int to, int id)
31 {
32     edge[tot].to = to;
33     edge[tot].id = id;
34     edge[tot].next = head[from];
35     head[from] = tot++;
36 }
37 
38 void solve (int u, int time)
39 {
40     dis[u] = time;
41     for (int i=head[u]; i!=-1; i=edge[i].next)
42     {
43         int v = edge[i].to;
44         if (vis[v])
45             continue;
46         vis[v] = true;
47         ans[edge[i].id] = true;
48     }
49 }
50 
51 int main ()
52 {
53     int t, n, m;
54     scanf ("%d", &t);
55     while (t --)
56     {
57         init ();
58         scanf ("%d %d", &n, &m);
59         
60         for (int i=1; i<=m; i++)
61         {
62             scanf ("%d %d", &p[i].l, &p[i].r);
63             Add (p[i].l, p[i].r, i);
64         }
65         
66         int s = 1, e = n, x = 0;
67         vis[s] = true;
68         
69         while (s <= e)
70         {
71             if (vis[s])
72                 solve (s++, x++);
73             if (vis[e])
74                 solve (e--, x++);
75         }
76         
77         for (int i=1; i<=m; i++)
78             if (ans[i])
79                 printf ("%d\n", abs(dis[p[i].l] - dis[p[i].r]));
80             else
81                 printf ("%d\n", n);
82                 
83     }
84     return 0;
85 }

 

转载于:https://www.cnblogs.com/alihenaixiao/p/4730634.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值