Atcoder Snuke's Subway Trip 重构图

Posted unnamed05

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Atcoder Snuke's Subway Trip 重构图相关的知识,希望对你有一定的参考价值。

题目链接

  这题主要是重构图的方法很难思考。

  方法一:考虑在每个公司意义下的联通块,每个联通块对应一个虚拟节点,联通块内的节点到联通块对应的虚拟节点有一条边,构建出一个二分图,跑一遍BFS,将经过的边数除以2。这里有两种实现,                             细节都注释在了程序里

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 vector<pair<int,int> > nei[1000005];
 4 vector<int> cit[1000005];
 5 vector<int>comp;
 6 int col[1000005];
 7 bool vis[1000005];
 8 vector<int>newnei[1000005];
 9 int dp[1000005];
10 int poi[1000005];
11 queue<int> q;                //无需跑最短路,直接写bfs,用queue 
12 int main()
13 {
14     int n,m;
15     cin>>n>>m;
16     memset(col,-1,sizeof col);
17     for(int i=0;i<m;i++)
18     {
19         int x,y,c;
20         scanf("%d %d %d",&x,&y,&c);
21         x--,y--,c--;
22         nei[x].push_back(make_pair(c,y));
23         nei[y].push_back(make_pair(c,x));
24         cit[c].push_back(x);
25         cit[c].push_back(y);
26         comp.push_back(c);
27     }
28     sort(comp.begin(),comp.end());
29     comp.erase(unique(comp.begin(),comp.end()),comp.end());
30     for(int i=0;i<n;i++)
31     {
32         sort(nei[i].begin(),nei[i].end());
33     }
34     int newci=n;
35     for(int i=0;i<comp.size();i++)
36     {
37         int cmp=comp[i];
38         for(int j=0;j<cit[comp[i]].size();j++)
39         {
40             int v=cit[comp[i]][j];
41             if(col[v]==cmp) continue;
42             q.push(v);
43             col[v]=cmp;
44             vector<int> ciin;
45             while(!q.empty())
46             {
47                 v=q.front();
48                 ciin.push_back(v);
49                 q.pop();
50                 int k=0;
51                 for(;poi[v]<nei[v].size();poi[v]++)            //这里的poi[v]很好的利用了按公司编号从小到大的单调性 
52                 {
53                     k=poi[v];
54                     if(nei[v][k].first!=cmp) break;
55                     int u=nei[v][k].second;
56                     if(col[u]==cmp) continue;
57                     col[u]=cmp;
58                     q.push(u);
59                 }
60             }
61             for(int k=0;k<ciin.size();k++)
62             {
63                 int v=ciin[k];
64                 newnei[v].push_back(newci);
65                 newnei[newci].push_back(v);
66             }
67             newci++;
68         }
69     }
70     for(int i=0;i<newci;i++) dp[i]=-2;
71     dp[0]=1;
72     q.push(0);
73     while(!q.empty())
74     {
75         int v=q.front();
76         q.pop();
77         for(int k=0;k<newnei[v].size();k++)
78         {
79             int u=newnei[v][k];
80             if(dp[u]==-2)
81             {
82                 dp[u]=dp[v]+1;q.push(u);
83             }
84             
85         }
86     }
87     cout<<dp[n-1]/2;
88 }
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 vector<pair<int,int> > nei[1000005],cit[1000005];
 4 vector<int>comp;
 5 int vis[1000005];
 6 vector<int>newnei[1000005];
 7 int dp[1000005];
 8 int par[1000005];
 9 void init(int x)
10 {
11     par[x]=x;
12 }
13 int find(int x)
14 {
15     return (par[x]==x)?x:par[x]=find(par[x]);
16 }
17 void merge(int x,int y)
18 {
19     x=find(x);y=find(y);
20     par[x]=y;
21 }
22 queue<int> q;
23 int main()
24 {
25     int n,m;
26     cin>>n>>m;
27     for(int i=0;i<m;i++)
28     {
29         int x,y,c;
30         scanf("%d %d %d",&x,&y,&c);
31         x--,y--,c--;
32         cit[c].push_back(make_pair(x,y));
33         comp.push_back(c);
34     } 
35     sort(comp.begin(),comp.end());
36     comp.erase(unique(comp.begin(),comp.end()),comp.end());
37     int newci=n;
38     for(int i=0;i<comp.size();i++)
39     {
40         int cmp=comp[i];
41         for(int j=0;j<cit[cmp].size();j++)
42         {
43             int v=cit[cmp][j].first,u=cit[cmp][j].second;
44             init(v);init(u);
45             vis[v]=vis[u]=0;                                //用到哪些就将哪些初始化 
46         }
47         for(int j=0;j<cit[cmp].size();j++)
48         {
49             merge(cit[cmp][j].first,cit[cmp][j].second);
50         }
51         for(int j=0;j<cit[cmp].size();j++)
52         {
53             int v=cit[cmp][j].first;
54             v=find(v);
55             if(!vis[v])
56             {
57                 vis[v]=newci;
58                 newnei[v].push_back(newci);
59                 newnei[newci].push_back(v);
60                 newci++;
61             }
62             if(!vis[cit[cmp][j].first])
63             {
64                 int u=cit[cmp][j].first;
65                 newnei[vis[v]].push_back(u);
66                 newnei[u].push_back(vis[v]);
67                 vis[cit[cmp][j].first]=newci;
68             }
69             if(!vis[cit[cmp][j].second])
70             {
71                 int u=cit[cmp][j].second;
72                 newnei[vis[v]].push_back(u);
73                 newnei[u].push_back(vis[v]);
74                 vis[cit[cmp][j].second]=newci;
75             }
76         }
77     }
78     for(int i=0;i<newci;i++) dp[i]=-2;
79     dp[0]=1;
80     q.push(0);
81     while(!q.empty())
82     {
83         int v=q.front();
84         q.pop();
85         for(int k=0;k<newnei[v].size();k++)
86         {
87             int u=newnei[v][k];
88             if(dp[u]==-2)
89             {
90                 dp[u]=dp[v]+1;q.push(u);
91             }
92         }
93     }
94     cout<<dp[n-1]/2;
95 }

  方法二:对于每个节点V,设置虚拟节点VC,VC到V有一条边,若边(U,V)是由公司C造的,则VC到UC有一条边,所以虚拟节点到其它节点的边权为0,真实节点到虚拟节点的边权为1,跑一遍最短路

 1 #include<stdio.h>
 2 #include<vector>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 typedef pair<int, int>pii;
 7 typedef pair<pii, int>pi3;
 8 vector<pii>pat[600000];
 9 bool flag[600000];
10 int dist[600000];
11 int main()
12 {
13     int num, way;
14     scanf("%d%d", &num, &way);
15     vector<pii>zat;
16     vector<pi3>zp;
17     for (int i = 0; i < way; i++)
18     {
19         int za, zb, zc;
20         scanf("%d%d%d", &za, &zb, &zc);
21         za--, zb--, zc--;
22         zat.push_back(make_pair(za, zc));
23         zat.push_back(make_pair(zb, zc));
24         zp.push_back(make_pair(make_pair(za, zb), zc));
25         zp.push_back(make_pair(make_pair(zb, za), zc));
26     }
27     sort(zat.begin(), zat.end());
28     for (int i = 0; i < zat.size(); i++)
29     {
30         pat[num + i].push_back(make_pair(zat[i].first, 0));
31         pat[zat[i].first].push_back(make_pair(num + i, 1));
32     }
33     for (int i = 0; i < zp.size(); i++)
34     {
35         int l1 = lower_bound(zat.begin(), zat.end(), make_pair(zp[i].first.first, zp[i].second)) - zat.begin();
36         int l2 = lower_bound(zat.begin(), zat.end(), make_pair(zp[i].first.second, zp[i].second)) - zat.begin();
37         pat[l1 + num].push_back(make_pair(l2 + num, 0));
38     }
39     priority_queue<pii>que;
40     que.push(make_pair(0, 0));
41     fill(dist, dist + 600000, 1000000000);
42     for (;;)
43     {
44         if (que.empty())break;
45         pii z = que.top();
46         que.pop();
47         if (flag[z.second])continue;
48         flag[z.second] = true;
49         for (int i = 0; i < pat[z.second].size(); i++)
50         {
51             if (dist[pat[z.second][i].first]>-z.first + pat[z.second][i].second)
52             {
53                 dist[pat[z.second][i].first] = -z.first + pat[z.second][i].second;
54                 que.push(make_pair(-dist[pat[z.second][i].first], pat[z.second][i].first));
55             }
56         }
57     }
58     if (flag[num - 1])printf("%d
", dist[num - 1]);
59     else printf("-1
");
60 }

 

以上是关于Atcoder Snuke's Subway Trip 重构图的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder ARC061E Snuke's Subway Trip 最短路

Cat Snuke and a Voyage AtCoder - 2660

Snuke's Coloring 2-1

例题收藏◇例题·I◇ Snuke's Subway Trip

[ARC061E]すぬけ君の地下鉄旅行 / Snuke's Subway Trip

AtCoder Grand Contest 036D - Negative Cycle