Fishing Net(ZOJ-1015)(MCS实现)

Problem Description

In a highly modernized fishing village, inhabitants there make a living on fishery. Their major tools, fishing nets, are produced and fixed by computer. After catching fishes each time, together with plenty of fishes, they will bring back the shabby fishing nets, which might be full of leaks. Then they have to inspect those nets. If there exist large leaks, they have to repair them before launching out again.

Obviously, the smaller the leaks in the fishing nets are, the more fishes they will catch. So after coming back, those fishermen will input the information of the fishing nets into the computer to check whether the nets have leaks.

The checking principle is very simple: The computer regards each fishing net as a simple graph constructed by nodes and edges. In the graph, if any circle whose length (the number of edges) is larger than 3 must has at least one chord, the computer will output "Perfect" indicating that the fishnet has no leaks. Otherwise, "Imperfect" will be displayed and the computer will try to repair the net. 

Note: A circle is a closed loop, which starts from one node, passes through other distinct nodes and back to the starting node. A chord is an edge, which connects two different nodes on the circle, but it does not belong to the set of edges on the circle.

Input 

The input file contains several test cases representing different fishing nets. The last test case in the input file is followed by a line containing 0 0.

The first line of each test case contains two integers, n and m, indicating the number of nodes and edges on the net respectively, 1 <= n <= 1000. It is followed by m lines accounting for the details of the edges. Each line consists of two integers xi and yi, indicating there is an edge between node xi and node yi.

Output

For each test case, display its checking results. The word "Imperfect" suggests that the corresponding fishing net is leaking, while the word "Perfect" stands for a fishing net in good condition.

Follow the output for each net with a blank line.

Sample Input

4 4
1 2
2 3
3 4
4 1
3 3
1 2
2 3
3 1
0 0

Sample Output

Imperfect

Perfect

题意:多组数据,每组数据给出 n 个点 m 条边,如果图是弦图的话,输出 Perfect,如果图不是弦图的话,输出 ImPerfect

思路:弦图判定模版题,套用 MCS 模版即可

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); }
const double EPS = 1E-10;
const int MOD = 1E9+7;
const int N = 1000000;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;

struct Edge {
    int to,next;
    Edge() {}
    Edge(int to,int next):to(to),next(next) {}
};
struct MCS{
    Edge edge[N<<1];
    int head[N],tot;
    int n,m;
    bool vis[N];
    int id[N];//编号
    int label[N];//与多少标号点相邻
    int order[N];//完美消除序列
    vector<int> V[N];

    void init(int n,int m) {
        this->n=n;
        this->m=m;
        for(int i=1; i<=n; i++)
            V[i].clear();
        memset(head,-1,sizeof(head));
        memset(order,0,sizeof(order));
        memset(label,0,sizeof(label));
        memset(vis,0,sizeof(vis));
        memset(id,0,sizeof(id));
        tot=0;
    }

    void addEdge(int x,int y) {
        edge[tot].to=y;
        edge[tot].next=head[x];
        head[x]=tot++;
    }

    void mcs() {
        for(int i=1; i<=n; i++)
            V[0].push_back(i);
        int maxx=0;
        int now=0;
        for(int i=1; i<=n; i++) { //从前往后
            bool flag=false;
            while(!flag) {
                for(int j=V[maxx].size()-1; j>=0; j--) { //从后往前
                    if(vis[V[maxx][j]])
                        V[maxx].pop_back();
                    else {
                        flag=true;
                        now=V[maxx][j];
                        break;
                    }
                }
                if(!flag)
                    maxx--;
            }
            vis[now]=true;
            //逆序存放
            order[n-i+1]=now;
            id[now]=n-i+1;

            for(int j=head[now]; j!=-1; j=edge[j].next) {
                int to=edge[j].to;
                if(!vis[to]) {
                    label[to]++;
                    V[label[to]].push_back(to);
                    maxx=max(maxx,label[to]);
                }
            }
        }
    }
    int bucket[N];//桶
    int judge() { //判断是否是弦图
        memset(vis,0,sizeof(vis));
        memset(bucket,0,sizeof(bucket));
        for(int i=n; i>0; i--) {
            int cnt=0;

            int ret=1;
            for(int j=head[order[i]]; j!=-1; j=edge[j].next)
                if(id[edge[j].to]>i)
                    vis[bucket[++cnt]=edge[j].to]=1;

            for(int j=head[bucket[1]]; j!=-1; j=edge[j].next) {
                int to=edge[j].to;
                if(to!=bucket[1]&&vis[to]) {
                    if(vis[to]) {
                        ret++;
                        vis[to]++;
                    }
                }
            }
            for(int j=1; j<=cnt; j++)
                vis[bucket[j]]=0;
            if(cnt&&ret!=cnt)
                return false;
        }
        return true;
    }
    int getMaximumClique() { //计算最大团、最小着色
        int res=0;
        for(int i=1; i<=n; i++)
            res=max(res,label[i]+1);
        return res;
    }
    int getMaximumIndependentSet() { //计算最大独立集、最小团覆盖
        memset(vis,0,sizeof(vis));
        int res=0;
        for(int i=1; i<=n; i++) {
            if(!vis[order[i]]) {
                res++;
                vis[order[i]]=true;
                for(int j=head[order[i]]; j!=-1; j=edge[j].next)
                    vis[edge[j].to]=true;
            }
        }
        return res;
    }
}mcs;
int main() {
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&(n+m)) {
        mcs.init(n,m);
        for(int i=1; i<=m; i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            mcs.addEdge(x,y);
            mcs.addEdge(y,x);
        }
        mcs.mcs();

        if(!mcs.judge())//若不为弦图
            printf("Imperfect\n");
        else  //若为弦图
            printf("Perfect\n");
        printf("\n");
    }
    return 0;
}

 

posted @ 2022-09-20 22:52  老程序员111  阅读(15)  评论(0)    收藏  举报