E - Reachability from the Capital

题目链接:https://vjudge.net/contest/236513#problem/E
大意:给你n条边的关系,输入的第一个只指向第一个,然后让你判断要想从指定的点到达剩下的所有的点,问你最少需要添加多少条边才符合要求。

思路:首先使用tarjan算法进行染色,缩点。到最后判断 缩减后 入度为零的不含有城市中心的强连通子图的个数就可以了!!!

原因,染完色之后,如果有入度为0的强连通子图,那么这个点就可能符合,然后吧满足这些条件的记录一下。注意,在累加 的时候,不能将入度为0的含有城市中心的强连通子图计算在内,因为这个图中,有城市中心的强连通图中,这个图中的其他所有的点都能由城市中心到达,所以不用累加。

代码如下:

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
# define maxn 5005
vector<int >wakaka[maxn];
map<int,int>p;
stack<int>q;
int dfn[maxn],low[maxn],vis[maxn];
int out[maxn],cnt[maxn],color[maxn],in[maxn];
int num,ans;
void tarjan(int u)
{
    vis[u]=1;
    q.push(u);
    low[u]=dfn[u]=++num;
    int len=wakaka[u].size();
    for(int i=0; i<len; i++)
    {
        int v=wakaka[u][i];
        if(vis[v]==0)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        if(vis[v]==1)
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        ans++;
        int top;
        do
        {
            top=q.top();
            q.pop();
            vis[top]=-1;
            color[top]=ans;
        }
        while(top!=u);
    }
}
int main()
{
    int n,m,t;
    while(cin>>n>>m>>t)
    {
        num=ans=0;
        memset(vis,0,sizeof(vis));
        memset(cnt,0,sizeof(cnt));
        memset(out,0,sizeof(out));
        memset(in,0,sizeof(in));
        memset(color,0,sizeof(color));
        while(!q.empty())q.pop();
        for(int i=1; i<=n; i++)
        {
            wakaka[i].clear();
        }
        p.clear();
        for(int i=1; i<=m; i++)
        {
            int u,v;
            cin>>u>>v;
            p[u]++;
            p[v]++;
            wakaka[u].push_back(v);
        }
        for(int i=1; i<=n; i++)
        {
            if(vis[i]==0)
                tarjan(i);
        }
        //cout<<color[1]<<endl<<color[2]<<endl;
        for(int i=1; i<=n; i++)
        {
            int len=wakaka[i].size();
            for(int j=0; j<len; j++)
            {
                if(color[i]!=color[wakaka[i][j]])
                {
                    in[color[i]]++;
                    out[color[wakaka[i][j]]]++;
                }
            }
            cnt[color[i]]++;
        }
            int t1=0,t2=0;
            for(int i=1; i<=ans; i++)
            {
                if(in[i]==0)
                    t1++;
                if(out[i]==0&&i!=color[t])
                {
                    t2++;
                }
            }
            cout<<t2<<endl;
            //else {
            //cout<<max(t1,t2)<<endl;
            //}
            //}
        }
        return 0;
    }


猜你喜欢

转载自blog.csdn.net/let_life_stop/article/details/80906117