poj2513Colored Sticks(快排-二分-并查集-欧拉路)

14 篇文章 0 订阅

题意:就是给你一些木棒,木棒两头都有颜色,颜色相同的可以连接起来。问你是否可以将所有

木棒连接起来。

思路:一看到这些字符串,就立马想到用map标记字符串的下标,直接超时。

然后使用快排+二分来查找这些字符的下标。

还有一个注意的地方,这是一个无向图。因为这个WA了好几次。

无向欧拉路连通的条件是:所有的度数都是偶数或者只有两个是奇数。


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=550001;
int cnt_in[maxn],cnt_out[maxn],p[maxn];
int cnt_dushu[maxn];
char ss[maxn][20];
struct p
{
    char s1[20],s2[20];
} tp[maxn];
int cnt=1,kj=0;
struct node
{
    char str[20];
    bool operator<(const node &c)const
    {
        return strcmp(str,c.str)<0;
    }
} t[maxn];
int erfen(char *s)
{
    int l=0,r=kj;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(strcmp(s,ss[mid])>0)
            l=mid+1;
        else
            r=mid;
    }
    return l+1;
}
int cha(int x)
{
    if(p[x]==x)
        return x;
    return p[x]=cha(p[x]);
}
void bing(int x,int y)
{
    p[y]=x;
}
int main()
{
    int n=0;
    while(scanf("%s%s",tp[cnt].s1,tp[cnt].s2)!=EOF)
    {
        strcpy(t[n++].str,tp[cnt].s1);
        strcpy(t[n++].str,tp[cnt].s2);
        cnt++;
    }
    sort(t,t+n);
    kj=0;
    strcpy(ss[kj],t[0].str);
    kj=1;
    for(int i=1; i<n; i++)
        if(strcmp(t[i].str,t[i-1].str)!=0)
            strcpy(ss[kj++],t[i].str);
    memset(cnt_dushu,0,sizeof(cnt_dushu));
    for(int i=1; i<=kj; i++)
        p[i]=i;
    for(int i=1; i<cnt; i++)
    {
        int x=erfen(tp[i].s1);
        int y=erfen(tp[i].s2);
        //printf("%s %s\n",tp[i].s1,tp[i].s2);
        //printf("%d %d\n",x,y);
        cnt_dushu[x]++;
        cnt_dushu[y]++;
        x=cha(x);
        y=cha(y);
        if(x!=y)
            bing(x,y);
    }
    int sum=0;
    for(int i=1; i<=kj; i++)
        if(p[i]==i)
            sum++;
    if(sum>1)
    {
        puts("Impossible");
        return 0;
    }
    int f1=0,f2=0;
    for(int i=1; i<=kj; i++)
    {
        if(cnt_dushu[i]%2==0)
            f1++;
        else f2++;

    }
    if(f1==kj)
    {
        puts("Possible");
    }
    else if(f1==kj-2&&f2==2)
    {
        puts("Possible");
    }
    else
    {
        puts("Impossible");
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值