BZOJ3081Strange Regulations

10 篇文章 0 订阅

3081: [Cerc2011]Strange Regulations
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 25 Solved: 11
Description
在一个计算机网络中,连接两台计算机的电缆属于不同的公司。一项新的反垄断法规定,一家公司连接同一台计算机的电缆不能超过两条。为了避免资源浪费,另外一条法律规定,一家公司的电缆系统不能有冗余,即去掉任意一个电缆之后,至少一对之前连通的计算机要断开连接。由于这些公司不断的销售和购入电缆,要确定他们是否遵守这些规则十分的困难。你的任务是写一个程序完成这个任务
Input
多组测试数据。第一行是4个整数N,M,C,T——计算机的数量1<=N=8000,电缆的数量0<=M<=100000,公司的数量1<=C<=100,电缆销售/购入的数量0<=T<=100000。
接下来M行,每行三个整数Sj1,Sj2,Kj,代表这条电缆连接的两个服务器Sj1,Sj2以及电缆所属的公司Kj。初始状态是遵守规则的。
接下来行,每行3个整数Si1,Si2,Ki,表示公司购入了连接S1,S2的电缆。
4个0标志着测试文件的结束。
Output
对于每个测试数据,输出行:
“No Such Cable.” 如果这对服务器之前没有被一对电缆相连
“Already owned.” 如果这对电缆本来就属于这家公司
“Frobidden: monopoly.” 如果公司Ki已经有2条电缆与S1或S2相连
“Forbidden: redundant.” 如果公司Ki公司购入这条电缆后,会在其网络中形成环
“Sold” 操作成功
每组测试数据之后要输出一个空行
Sample Input
4 5 3 5
1 2 1
2 3 1
3 4 2
1 4 2
1 3 3
1 2 3
1 2 3
1 4 3
2 3 3
2 4 3
2 1 1 1
1 2 1
1 2 1
0 0 0 0
Sample Output
Sold.
Already owned.
Forbidden: monopoly.
Forbidden: redundant.
No such cable.

Already owned.
同BZOJ3651
多组数据要memset
附上本蒟蒻的代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
#define MAXN 8010
int n,m,colornum,T;
map<pair<int,int>,int>q;
struct kx
{
    int father[MAXN],c[MAXN][2],st[MAXN],degree[MAXN];
    bool rev[MAXN];
    kx()
      {
        memset(father,0,sizeof(father));memset(c,0,sizeof(c));memset(st,0,sizeof(st));
        memset(degree,0,sizeof(degree));memset(rev,false,sizeof(rev));
      }
    bool isroot(int x)
      {
        return c[father[x]][0]!=x && c[father[x]][1]!=x;
      }
    void rever(int x)
      {
        if (!x) return;
        swap(c[x][0],c[x][1]),rev[x]^=1;
      }
    void rotate(int x)
      {
        int y=father[x],z=father[y],l,r;
        if (c[y][0]==x) l=0;
        else l=1;
        r=l^1;
        if (!isroot(y))
          if (c[z][0]==y) c[z][0]=x;
          else c[z][1]=x;
        father[x]=z,father[y]=x,father[c[x][r]]=y,c[y][l]=c[x][r],c[x][r]=y;
      }
    void pushdown(int x)
      {
        int l=c[x][0],r=c[x][1];
        if (rev[x]) rever(c[x][0]),rever(c[x][1]),rev[x]=0;
      }
    void splay(int x)
      {
        int i,top=0,y,z;
        st[++top]=x;
        for (i=x;!isroot(i);i=father[i]) st[++top]=father[i];
        for (i=top;i;i--) pushdown(st[i]);
        while (!isroot(x))
          {
            y=father[x],z=father[y];
            if (!isroot(y))
              if (c[y][0]==x^c[z][0]==y) rotate(x);
              else rotate(y);
            rotate(x);
          }
      }
    int root(int x)
      {
        access(x),splay(x);
        while (c[x][0]) x=c[x][0];
        return x;
      }
    void access(int x)
      {
        int t;
        for (t=0;x;t=x,x=father[x]) splay(x),c[x][1]=t;
      }
    void link(int x,int y)
      {
        degree[x]++,degree[y]++,access(x),splay(x),rever(x),father[x]=y,access(x);
      }
    void cut(int x,int y)
      {
        degree[x]--,degree[y]--,access(x),splay(x),rever(x),access(y),splay(y),c[y][0]=father[c[y][0]]=0;
      }
    bool ask(int x,int y)
      {
        return root(x)==root(y);
      }
}color[110];

int read()
{
    int w=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9')
      {
        if (ch=='-') f=-1;
        ch=getchar();
      }
    while (ch>='0' && ch<='9')
      w=w*10+ch-'0',ch=getchar();
    return w*f;
}

int main()
{
    int i,x,y,w;
    while (n=read(),m=read(),colornum=read(),T=read())
      {
        if (!n && !m && !colornum && !T) break;
        memset(color,0,sizeof(color));
        for (i=1;i<=m;i++)
          {
             x=read(),y=read(),w=read();
             q[make_pair(min(x,y),max(x,y))]=w;
             color[w].link(x,y);
          }
        while (T--)
          {
             x=read(),y=read(),w=read();
             if (q[make_pair(min(x,y),max(x,y))]==0) 
               {
                 printf("No such cable.\n"); continue;
               }
             if (q[make_pair(min(x,y),max(x,y))]==w)
               {
                 printf("Already owned.\n"); continue;
               }
             if (color[w].degree[x]==2 || color[w].degree[y]==2 || (x==y && color[w].degree[x]!=0))
               {
                 printf("Forbidden: monopoly.\n"); continue;
               }
             if (color[w].ask(x,y)==1)
               {
                 printf("Forbidden: redundant.\n"); continue;
               }
             printf("Sold.\n");
             int s=q[make_pair(min(x,y),max(x,y))];
             color[s].cut(x,y),color[w].link(x,y),q[make_pair(min(x,y),max(x,y))]=w;
          }
        printf("\n");
      }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值