BZOJ3651網絡通信

3651: 網絡通信
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 77 Solved: 54
Description
有一個由M 條電纜連接的 N 個站點組成的網絡。爲了防止壟斷,由 C 個公司控制所有的電纜,規定任何公司不能控制連接同一個站點的兩條以上的電纜(可以控制兩條)。同時規定,每個公司不能有多餘的電纜,所謂的多餘,是指屬於同一個公司的電纜不能形成環。
在運作過程中,不同公司之間會進行電纜買賣。請你寫一個程序判斷買賣是否合法。
Input
輸入第一行有4個由空格隔開的整數 N,M,C和 T。N(1≤N≤ 8 000)表示站點數,M(0≤M≤100 000)表示連接站點的電纜數。C(1≤C≤ 100)表表示公司數量,T 表示電纜買賣次
數。後面有M行,每行三個整數Sj1,Sj2和Kj,表示連接站點Sj1和Sj2(1≤Sj1< Sj2 ≤ n)的電纜屬於Kj(1≤Kj≤C)公司擁有,任意兩個站點只有一條直接相連的電纜,輸入狀態合法。最後T(0≤T≤100 000)行,每行三個整數 Si1, Si2和 Ki,表示 Ki公司想購買站點Si1和Si2之間的電纜。
Output
輸出共 T行,表示處理的結果,有以下幾種可能的結果:
1、“No such cable.” 兩個站點間沒有電纜。
2、 “Already owned.” 電纜己經是 Ki 公司控制。
3、 “Forbidden: monopoly.” Ki 公司己經控制了兩條連接 Si1 或 Si2 的電纜。
4、 “Forbidden: redundant.” Ki 公司控制的線路會出現環。
5、 “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
Sample Output
Sold.
Already owned.
Forbidden: monopoly.
Forbidden: redundant.
No such cable.
LCT模板題。。
LCT維護雙連通分量模板。。
雙倍經驗:BZOJ3081
CA互測題。。
在考場上寫了個200+的鏈剖,然後MLE。。
另一種TA爺神奇的做法是splay+啓發式合併。。
對於No such cable和Already owned,map一下。。
如果爲0——>No such cable
如果爲顏色——>Already owned
然後增設變量degree,記錄同種顏色邊的度數。。
如果==2——>Forbidden: monopoly
然後維護下連通性。。
如果x與y連通——>Forbidden: redundant
如果都不是——>Sold
然後修改。。cut再link
附上本蒟蒻的代碼:

#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;
    n=read(),m=read(),colornum=read(),T=read();
    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;
      }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章