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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值