[bzoj] 1077: [SCOI2008]天平

来源:互联网 发布:江西淘宝村 编辑:程序博客网 时间:2024/05/25 19:56

看了并查集神做法,发现后面还是暴力。。

先用并查集将各个相等的砝码连在一起作为一个整体。

然后根据当前条件求出可以求出的值,不能求出具体值的求出可能是1-2还是2-3。

然后就是最重要的,枚举i,j再枚举a,b,i,j可能的值。

因为题目要将只有唯一的选法加入,所以如果4个砝码出现同时存在>,<,=其中大于两种情况,就不选。

建议可以去看看fuxey的

#include <cstdio>#include <vector> using namespace std;const int N=55;vector<int> que;int n,a,b,fa[N],ans1,ans2,ans3;char ch[N][N];int vl[6],kl[6];int g[N][N],val[N],l[N],r[N];int getf(int x){    return fa[x]==x?x:(fa[x]=getf(fa[x]));}inline void link(int x,int y){    int fx=getf(x),fy=getf(y);    if(fx==fy) return;    fa[fx]=fy;    return ;}inline int pd(int x){    if (x==0) return 0;    if (x>0) return 1;    return -1;}int main(){    register int i,j;//,k,v;    scanf("%d %d %d",&n,&a,&b);    for (i=1;i<=n;i++)    {        scanf("%s",ch[i]);        fa[i]=i;    }    for (i=n;i>=1;i--)    {        for (j=n;j>=1;j--)        {            ch[i][j]=ch[i][j-1];        }     }    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    {        if (ch[i][j]=='=') link(i,j);    }    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    {        if (ch[i][j]=='+') g[getf(i)][getf(j)]=1,g[getf(j)][getf(i)]=-1;        if (ch[i][j]=='-') g[getf(i)][getf(j)]=-1,g[getf(j)][getf(i)]=1;    }    for (i=1;i<=n;i++) if (getf(i)==i) que.push_back(i);    for (i=0;i<que.size();i++)    {        int big=0,small=0;        for (j=0;j<que.size();j++)        big|=(g[que[i]][que[j]]==1),small|=(g[que[i]][que[j]]==-1);        if (!big||!small) continue;        val[que[i]]=2;        for (j=0;j<que.size();j++)        {            if (g[que[i]][que[j]]) val[que[j]]=2-g[que[i]][que[j]];        }    }    int x;    for (i=0;i<que.size();i++)    {        x=que[i];        l[x]=1;r[x]=3;        if (val[x]) l[x]=r[x]=val[x];        else        {            for (j=0;j<que.size();j++)            {                if(g[x][que[j]]==1) l[x]=2;                else if(g[x][que[j]]==-1) r[x]=2;            }        }    }    bool fl;    int p1=0,p2=0,p3=0;    kl[1]=a;kl[2]=b;    for (i=1;i<=n;i++)    {        if (i!=a&&i!=b)        for (j=i+1;j<=n;j++)        if (j!=a&&j!=b)        {            p1=p2=p3=0;                for (vl[1]=l[fa[a]];vl[1]<=r[fa[a]];vl[1]++)                for (vl[2]=l[fa[b]];vl[2]<=r[fa[b]];vl[2]++)                for (vl[3]=l[fa[i]];vl[3]<=r[fa[i]];vl[3]++)                for (vl[4]=l[fa[j]];vl[4]<=r[fa[j]];vl[4]++)                {                    kl[3]=i;kl[4]=j;                    fl=true;                    for (int k=1;k<=4;k++)                    for (int v=k+1;v<=4;v++)                    {                        if (fa[kl[k]]==fa[kl[v]]&&vl[k]!=vl[v]) {fl=false;k=5;break;}                        else if (g[fa[kl[k]]][fa[kl[v]]]&&g[fa[kl[k]]][fa[kl[v]]]!=pd(vl[k]-vl[v])) {fl=false;k=5;break;}                    }                    if (!fl) continue;                    if(vl[1]+vl[2]==vl[3]+vl[4])                    {                        p2=1;                    }                     if(vl[1]+vl[2]<vl[3]+vl[4])                    {                        p3=1;                    }                     if(vl[1]+vl[2]>vl[3]+vl[4])                    {                        p1=1;                    }                 }                if (p1+p2+p3==1) ans1+=p1,ans2+=p2,ans3+=p3;        }    }    printf("%d %d %d\n",ans1,ans2,ans3);    return 0;}



原创粉丝点击