码迷,mamicode.com
首页 > 其他好文 > 详细

Gym-101630C:Connections(生成树&构造)

时间:2018-07-16 23:12:19      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:can   i++   clu   输出   return   pac   反向   efi   clear   

题意:给定N点,M条有向边,满足任意点可以到达任意点。现在叫你保留2*N边,任然满足任意点可以到达任意点,输出删除的边。

思路:从1出发,DFS,得到一颗生成树,有N-1条边。反向建题。还是从1出发,得到一颗生成树,这2N-2条边显然可以满足任意点互通。然后随便选两边即可。 (任意点u->v,至少有u->1->v满足。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
const int maxn=200010;
using namespace std;
int u[maxn],v[maxn],vis1[maxn],vis2[maxn],N;
vector<int>G1[maxn],G2[maxn];
map<pii,int>mp;
void dfs1(int u)
{
    vis1[u]=1; int L=G1[u].size();
    for(int i=0;i<L;i++) if(!vis1[G1[u][i]]) mp[make_pair(u,G1[u][i])]=1,dfs1(G1[u][i]);
}
void dfs2(int u)
{
    vis2[u]=1; int L=G2[u].size();
    for(int i=0;i<L;i++) if(!vis2[G2[u][i]]) mp[make_pair(G2[u][i],u)]=1,dfs2(G2[u][i]);
}
int main()
{
    int T,M,i,j;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M);
        mp.clear(); memset(vis1,0,sizeof(vis1)); memset(vis2,0,sizeof(vis2));
        for(i=1;i<=N;i++) G1[i].clear(),G2[i].clear();
        for(i=1;i<=M;i++){
            scanf("%d%d",&u[i],&v[i]);
            G1[u[i]].push_back(v[i]);
            G2[v[i]].push_back(u[i]);
        }
        dfs1(1); dfs2(1);
        int cnt=M-N-N;
        for(i=1;i<=M&&cnt;i++){
           if(!mp[make_pair(u[i],v[i])]) printf("%d %d\n",u[i],v[i]),cnt--;
        }
    }
    return 0;
}

 

Gym-101630C:Connections(生成树&构造)

标签:can   i++   clu   输出   return   pac   反向   efi   clear   

原文地址:https://www.cnblogs.com/hua-dong/p/9320738.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!