Gym101630C Connections

题目大意:

  给出一个\(n\)个点\(m\)条边的有向图,无自环无重边。要求把这个图进行删边,直到只剩下\(2n\)条边,使得图中每个点都可以相互连通。

知识点:  DFS

解题思路:

  从点\(1\)出发,进行一次\(DFS\),把所有的点都访问一次,标记经过的边,这些边保证了点\(1\)能到所有的点。再额外建一个图(图中所有的边都是原图的边的反向),再进行一次与上面类似的DFS操作:从点\(1\)出发,把所有的点都访问一次,标记经过的边,这些边保证了所有的点都能到点\(1\)。两次\(DFS\)最多标记\(2n-2\)条边,并保证了所有点都能到点\(1\),点\(1\)能到所有点,如此所有点都能到所有点,每个点都可以相互连通。被标记的边就是必需的,删除其他边直到只剩下\(2n\)条边即可。

AC代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef pair<int,int> P;
 5 const int maxn=100000+5;
 6 vector<int>G[maxn],tG[maxn];
 7 P edge[maxn];
 8 map<P,int> used;
 9 int n;
10 bool vis[maxn];
11 void init(){
12     for(int i=1;i<=n;i++)   vis[i]=false;
13 }
14 void dfs1(int rt){
15     for(int i=0;i<G[rt].size();i++){
16         if(!vis[G[rt][i]]){
17             vis[G[rt][i]]=true;
18             dfs1(G[rt][i]);
19             used[make_pair(rt,G[rt][i])]++;
20         }
21     }
22 }
23 void dfs2(int rt){
24     for(int i=0;i<tG[rt].size();i++){
25         if(!vis[tG[rt][i]]){
26             vis[tG[rt][i]]=true;
27             dfs2(tG[rt][i]);
28             used[make_pair(tG[rt][i],rt)]++;
29         }
30     }
31 }
32 int main(){
33     int t;
34     scanf("%d",&t);
35     while(t--){
36         int m,u,v;
37         scanf("%d%d",&n,&m);
38         used.clear();
39         for(int i=1;i<=n;i++){
40             G[i].clear();
41             tG[i].clear();
42         }
43         for(int i=1;i<=m;i++){
44             scanf("%d%d",&u,&v);
45             G[u].push_back(v),tG[v].push_back(u);
46             edge[i]=make_pair(u,v);
47         }
48         init();
49         vis[1]=true;
50         dfs1(1);
51         init();
52         vis[1]=true;
53         dfs2(1);
54         int has=m;
55         for(int i=1;i<=m&&has>2*n;i++){
56             if(used[edge[i]]==0){
57                 printf("%d %d\n",edge[i].first,edge[i].second);
58                 has--;
59             }
60         }
61     }
62     return 0;
63 }

 

posted @ 2018-01-23 17:36  Blogggggg  阅读(125)  评论(0编辑  收藏  举报