VIJOS-P1626 愛在心中

https://neooj.com:8081/oldoj/problem.php?id=1588
神奇。。。
tarjan 水題
WA 一次

第一次:

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int to[10004],next[10004],head[1003],cnt;
void add(int x,int y){to[++cnt]=y;next[cnt]=head[x];head[x]=cnt;}
int min(int x,int y){return x<y?x:y;}
int z[1003],inz[1003],top;
int v[1003],deep[1003],low[1003],tot;
int f[1003][1003],ans;
int belong[1003];
int frudu[1003];
void tarjan(int x)
{
    z[++top]=x;inz[x]=1;v[x]=1;
    deep[x]=low[x]=++tot;
    for(int i=head[x];i;i=next[i])
    {
        if(v[to[i]]==0) tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
        else if(inz[to[i]]==1) low[x]=min(low[x],deep[to[i]]);
    }
    if(deep[x]==low[x])
    {
        ans++;
        int t;
        do
        {
            t=z[top--];inz[t]=0;
            f[ans][++f[ans][0]]=t;
            belong[t]=ans;
        }while(t!=x);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(int i=1;i<=n;i++)
    {
        if(!v[i])
        {
            tarjan(i);
        }
    }
    int love=0;
    for(int i=1;i<=ans;i++)
    {
        if(f[i][0]!=1)love++;
    }
    printf("%d\n",love);
    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j;j=next[j])
        {
            if(belong[i]!=belong[to[j]])
            {
                frudu[belong[to[j]]]++;
            }
        }
    }
    int temp=0;
    for(int i=1;i<=ans;i++)
    {
        if(frudu[i]==ans-1&&f[i][0]!=1)
        {
            temp=1;
            int x=f[i][0];
            sort(f[i]+1,f[i]+x+1);
            for(int j=1;j<=f[i][0];j++)
            {
                printf("%d ",f[i][j]);
            }
            printf("\n");
        }
    }
    if(temp==0)
    {
        printf("-1\n");
    }
    return 0;
}

tarjan 後 縮點 計算入度,若 入度=點數-1 則爲所求。
明顯錯誤!!!!!!!!!!!!!!!!
eg:


正解爲:
tarjan 後縮點計算出度,如果出度爲0的點的個數爲1,那麼就是我們要找到的答案,排序輸出。
否則,如果個數大於1,或者此點不是愛心天使,那麼就輸出‘-1’。

因爲:這裏寫圖片描述
如果爲這種情況,則1,2,3爲一個強連通分量。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#define kkklll 10002
using namespace std;
int to[10002],next[10002],head[1002],cnt;
void add(int x,int y){to[++cnt]=y;next[cnt]=head[x];head[x]=cnt;}
int rudu[1002],chudu[1002];
int min(int a,int b){return a<b?a:b;}
int deep[1002],low[1002],tim,v[1002],z[1002],inz[1002],top;
int ans,f[1002][1002],in[1002];
void tarjan(int x)
{
    z[++top]=x,inz[x]=1,v[x]=1;
    deep[x]=low[x]=++tim;
    for(int i=head[x];i;i=next[i])
    {
        if(v[to[i]]==0) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}
        else{if(inz[to[i]]==1){low[x]=min(low[x],deep[to[i]]);}}
    }
    if(deep[x]==low[x])
    {
        ans++;
        int t;
        while(1)
        {
            t=z[top--];inz[t]=0;f[ans][++f[ans][0]]=t;in[t]=ans;
            if(t==x){break;}
        }
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i,j;
    for(i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        rudu[b]++;
    }
    for(i=1;i<=n;i++)
    {
        if(v[i]==0)
        {
            tarjan(i);
        }
    }
    int ans1=0;
    for(i=1;i<=ans;i++)
    {
        if(f[i][0]!=1) ans1++;
    }
    printf("%d\n",ans1);
    for(i=1;i<=n;i++)
    {
        for(j=head[i];j;j=next[j])
        {
            if(in[to[j]]!=in[i])
            {chudu[in[i]]++;}
        }
    }
    int sum=0;
    int pos;
    for(i=1;i<=ans;i++)
    {
        if(chudu[i]==0){sum++;pos=i;}
    }
    if(sum!=1||f[pos][0]==1){printf("-1");}
    else
    {
        int a=f[pos][0];
        f[pos][0]=0;
        sort(f[pos]+1,f[pos]+a+1);
        for(i=1;i<=a;i++)
        {
            printf("%d ",f[pos][i]);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章