【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel

有趣的思考题

Description

Input

* 第一行: 两个空格分开的数, N和M

* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

Output

* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.


 

题目分析

做法一

暴力树剖线段树

做法二

并查集[bzoj1576] [Usaco2009 Jan]安全路经Travel

 1 #include<bits/stdc++.h>
 2 const int maxn = 100035;
 3 const int maxm = 400035;
 4 
 5 int n,m,dis[maxn];
 6 struct cmp
 7 {
 8     bool operator ()(int a, int b) const
 9     {
10         return dis[a] > dis[b];
11     }
12 };
13 struct Edge
14 {
15     int y,val;
16     Edge(int a=0, int b=0):y(a),val(b) {}
17 }edges[maxm];
18 struct EdgeSv
19 {
20     int x,y,dis;
21     bool operator < (EdgeSv a) const
22     {
23         return dis < a.dis;
24     }
25     EdgeSv(int a=0, int b=0, int c=0):x(a),y(b),dis(c) {}
26 }edgeSv[maxm];
27 int fa[maxn],fat[maxn],tag[maxn],dep[maxn];
28 bool disVis[maxn],treeTag[maxm];
29 int edgeTot,svTot,nxt[maxm],pre[maxm],head[maxn];
30 std::priority_queue<int, std::vector<int>, cmp> q;
31 
32 int read()
33 {
34     char ch = getchar();
35     int num = 0;
36     bool fl = 0;
37     for (; !isdigit(ch); ch = getchar())
38         if (ch=='-') fl = 1;
39     for (; isdigit(ch); ch = getchar())
40         num = (num<<1)+(num<<3)+ch-48;
41     if (fl) num = -num;
42     return num;
43 }
44 void addedge(int u, int v)
45 {
46     int c = read();
47     edges[++edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot;
48     edges[++edgeTot] = Edge(u, c), nxt[edgeTot] = head[v], head[v] = edgeTot;
49 }
50 int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
51 int main()
52 {
53     memset(dis, 0x3f3f3f3f, sizeof dis);
54     memset(head, -1, sizeof head);
55     n = read(), m = read();
56     for (int i=1; i<=n; i++) fa[i] = i;
57     for (int i=1; i<=m; i++) addedge(read(), read());
58     dis[1] = 0, q.push(1);
59     while (q.size())
60     {
61         int tt = q.top();
62         q.pop();
63         for (int i=head[tt]; i!=-1; i=nxt[i])
64             if (dis[edges[i].y] > dis[tt]+edges[i].val){
65                 dis[edges[i].y] = dis[tt]+edges[i].val;
66                 dep[edges[i].y] = dep[tt]+1, pre[edges[i].y] = i, fat[edges[i].y] = tt;
67                 q.push(edges[i].y);
68             }
69     }
70     for (int i=2; i<=n; i++) treeTag[pre[i]] = 1;
71     for (int i=1; i<=edgeTot; i+=2)
72         if (!treeTag[i]&&!treeTag[i+1]){
73             int u = edges[i].y, v = edges[i+1].y;
74             edgeSv[++svTot] = EdgeSv(u, v, edges[i].val+dis[u]+dis[v]);
75         }
76     std::sort(edgeSv+1, edgeSv+svTot+1);
77     for (int i=1; i<=svTot; i++)
78     {
79         int u = edgeSv[i].x, v = edgeSv[i].y, lstu = 0, lstv = 0;
80         int topu = get(u), topv = get(v);
81         while (topu!=topv)
82         {
83             if (dep[topu] < dep[topv])
84                 std::swap(u, v), std::swap(lstu, lstv), std::swap(topu, topv);
85             if (!tag[u]){    
86                 tag[u] = i;
87                 if (lstu) fa[lstu] = u;
88             }else if (lstu) fa[lstu] = topu;
89             lstu = topu, u = fat[topu], topu = get(u);
90         }
91     }
92     for (int i=2; i<=n; i++)
93         if (!tag[i]) puts("-1");
94         else printf("%d\n",edgeSv[tag[i]].dis-dis[i]);
95     return 0;
96 }

 

 

END

posted @ 2018-09-26 21:53  AntiQuality  阅读(153)  评论(0编辑  收藏  举报