zoukankan      html  css  js  c++  java
  • 再不做题就老了,这个假期就这么地了

    1.POJ 2186

    题意:有n头牛和m个有向关系表示两个牛有暧昧关系,牛还都挺喜欢自己的,问你有多少牛是被全体喜欢的。

    理解:一看到全体就知道要求两两可达的强连通分量,要是只有一个联通分量就说明每个牛都和其他牛暧昧,多余一个联通分量那就要看他们是不是连成串,穿成串那最后一个出度为0的就是牛中最high的牛群,但要是有个出度大于1或存在2个出度为0的联通分量,就没有那么好的牛了,所以Tarjan对图分析一遍,得到缩的点之间的出度关系。

    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <iostream>
    using namespace std;
    const int MAXN = 100002;
    int in[MAXN], out[MAXN];
    
    vector<int> G[MAXN];
    int dfn[MAXN],low[MAXN],belong[MAXN],belong_cnt[MAXN];
    int Count,n,m,cnt;
    bool instack[MAXN];
    stack <int>stap;
    
    void init(){
        Count=cnt=0;
        memset(dfn,0,sizeof(dfn));
        memset(belong,0,sizeof(belong));
        memset(instack,0,sizeof(instack));
        memset(belong_cnt,0,sizeof(belong_cnt));
    }
    
    void tarjan(int x){
        int i;
        dfn[x]=low[x]=++cnt;
        stap.push(x);
        instack[x]=1;
        for(i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[v],low[x]);
            }else if(instack[v])
                low[x]=min(dfn[v],low[x]);
        }
        
        if(low[x]==dfn[x]){
            Count++;
            while(1){
                int tmp=stap.top();
                stap.pop();
                belong[tmp]=Count;
                belong_cnt[Count]++;
                instack[tmp]=0;
                if(tmp==x) break;
            }
        }
    }
    
    void work(){
        init();
        for(int i=0;i<n;i++)
            if(!dfn[i]) tarjan(i);
    }
    void Topsort(){
        memset(in, 0, sizeof(in));
        memset(out, 0, sizeof(out));
        for (int u = 0; u < n; u++)
            for (int i = 0; i < G[u].size(); i++){
                int v = G[u][i];
                if (belong[u] != belong[v]){
                    in[belong[v]] ++;
                    out[belong[u]] ++;
                }
            }
    }
    
    int main(){
        int x, y;
        while(~scanf("%d%d", &n, &m)){
            for (int i = 0; i <= n; i++)
                G[i].clear();
            
            while(m--){
                scanf("%d%d", &x, &y);
                x--; y--;
                G[x].push_back(y);
            }
            work();
            if(Count == 1) {printf("%d
    ", n);continue;}
            
            Topsort();
            int c = 0,ans=0;
            for (int i = 1; i <=Count; i++){
                if (out[i] == 0) c++, ans=belong_cnt[i];
            }
            if(c>1)
                printf("0
    ");
            else
                printf("%d
    ", ans);
        }
        return 0;
    }
    View Code

    2.POJ 3020

    题意:有些格子中的点,要我们用最少的可以覆盖两个相邻点的圈,覆盖所有的点。

    理解:http://www.cnblogs.com/updateofsimon/p/3441343.html 最小路径覆盖问题,将每个点拆成两个点一左一右,相邻的点连线,求个最大匹配,每2个表示一种匹配,所以结果就是 点个数 - 最大匹配/2

    #include <cstdio>
    #include <cstring>
    #define MAXN 405
    int point[41][11];
    int G[MAXN][MAXN],link[MAXN],used[MAXN],n,m;
    
    bool path(int u) {
        for(int i=1;i<=n;i++)
            if(G[u][i] && !used[i]) {
                used[i] = 1;
                if(link[i]==-1 || path(link[i])) {
                    link[i] = u;
                    return true;
                }
            }
        return false;
    }
    
    void hungary() {
        int ans = 0;
        memset(link,-1,sizeof(link));
        for(int i=1;i<=n;i++) {
            memset(used,0,sizeof(used));
            if(path(i)) ans++;
        }
        printf("%d
    ", n-ans/2);
    }
    int main() {
        int T;
        int x,y;
        int dir[4][2]={0,-1,0,1,-1,0,1,0};
        scanf("%d",&T);
        while(T--) {
            n = 0;
            char ch;
            scanf("%d%d",&x,&y);
            memset(point,0,sizeof(point));
            memset(G,0,sizeof(G));
            for(int i = 0; i < x; i++) {
                getchar();
                for (int j = 0; j < y; j++) {
                    ch=getchar();
                    if (ch=='*')
                        point[i][j] = ++n;
                }
            }
            for (int i = 0; i < x; i++) {
                for (int j = 0; j < y; j++) {
                    if(point[i][j])
                        for (int d = 0; d < 4; d++)
                            if(i+dir[d][0]>= 0 && i+dir[d][0] < x && j+dir[d][1] >= 0 && j+dir[d][1] < y)
                                if(point[i+dir[d][0]][j+dir[d][1]])
                                G[point[i][j]][point[i+dir[d][0]][j+dir[d][1]]] = 1;
                }
            }
            hungary();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    iptables学习笔记_____摘自朱双印个人日志 ____http://www.zsythink.net/
    使用xmanager图形化远程连接rhel6
    powerdesigner
    CentOS和RedHat Linux的区别
    win7防火墙端口开放
    微服务 环境问题处理
    lombok
    pl/sql Devloper 如何查看表结构
    pl/sql Devloper使用
    luogu P4231 三步必杀
  • 原文地址:https://www.cnblogs.com/updateofsimon/p/3549468.html
Copyright © 2011-2022 走看看