Assignment 6: Basic Graph Algorithms

  • 1308 Is It A Tree? (1)

  • 1258 Agri-Net (2)

  • 2488 A Knight's Journey (3)

  • 1164 The Castle (3)

  • 2395 Out of Hay (4)

  • 3177 Redundant Paths (4)

  • 1945 Power Hungry Cows (5)

  • 3275 Ranking the Cows (6)

  • 1985 Cow Marathon (7)

  • 2337 Catenyms (7)

  • 2186 Popular Cows (8, challenge problem)

  • 1944 Fiber Communications (8, challenge problem)


    poj2395

    最小生成树的最大边

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int fa[2010];
    
    struct EDGE {
        int u, v, c;
    
        bool operator<(const EDGE &t)const {
            return c < t.c;
        }
    };
    
    int find(int x) {
        if (x != fa[x])
            fa[x] = find(fa[x]);
        return fa[x];
    }
    
    EDGE edge[10010];
    
    int main() {
        int n, m, a, b, c, i;
        scanf("%d%d", &n, &m);
        for (i = 1; i <= n; ++i)
            fa[i] = i;
        int cnt = 0;
        for (i = 0; i < m; ++i) {
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].c);
        }
        sort(edge, edge + m);
        for (i = 0; i < m; ++i) {
            a = find(edge[i].u);
            b = find(edge[i].v);
            if (a != b) {
                ++cnt;
                if (cnt == n - 1)
                    break;
                fa[a] = b;
            }
        }
        printf("%d\n", edge[i].c);
        return 0;
    }

    poj3177

    求双连通分量后缩点,判叶子节点数加一除二。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int d[5010],low[5010];
    bool vis[5010][5010],mat[5010];
    int m,n,tot;
    vector <int> adj[5010];
    void dfs(int u,int p){
        int v;
        mat[u]=1;
        vector <int>::iterator it;
        low[u]=tot++;
        for(it=adj[u].begin();it!=adj[u].end();++it){
            v=*it;
            if(v==p) continue;
            if(!mat[v]) dfs(v,u);
            low[u]=min(low[u],low[v]);
        }
    }
    int main(){
       //  freopen("test.in","r",stdin);
        int i,u,v,ans;
        vector <int>::iterator it;
        while(scanf("%d%d",&n,&m)!=EOF){
            memset(d,0,sizeof(d));
            memset(vis,0,sizeof(vis));
            for(i=1;i<=n;++i) adj[i].clear();
            while(m--){
                scanf("%d%d",&u,&v);
                if(vis[u][v] || vis[v][u]) continue;
                vis[u][v]=1;
                adj[u].push_back(v);
                adj[v].push_back(u);
            }
            tot=0;
            dfs(1,0);
            for(u=1;u<=n;++u){
                for(it=adj[u].begin();it!=adj[u].end();++it){
                    v=*it;
                    if(low[u]!=low[v]){
                        d[low[u]]++;
                    }
                }
            }
            ans=0;
            for(u=0;u<n;++u){
                if(d[u]==1) ans++;
            }
            printf("%d\n",(ans+1)>>1);
        }
        return 0;
    }

    poj1945

    A*启发+广搜+优先队列

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define maxn 80010
    int n;
    
    void swap(int &a,int &b){
        int t=a;
        a=b;
        b=t;
    }
    
    typedef struct S{
        int x,y,s,c;
        S(){}
        S(int xx,int yy,int ss):x(xx),y(yy),s(ss){}
        S(const S& temp){
            x=temp.x,y=temp.y,s=temp.s,c=temp.c;
        }
        bool operator<(const S t)const{
            return c>t.c;
        }
        void out(){
            printf("%d %d %d %d\n",x,y,s,c);
        }
    }NODE;
    NODE now,next;
    priority_queue <NODE> pq;
    
    typedef struct SS{
        int x,y,s;
        SS(){}
        SS(int xx,int yy,int ss):x(xx),y(yy),s(ss){}
    }HASH;
    vector<HASH> hash[maxn];
    
    void cal(NODE &node){
        int temp=n/node.x,cnt=0;
        while(temp){
            ++cnt;
            temp>>=1;
        }
        node.c=node.s+cnt;
    }
    
    bool gaoh(NODE &node){
        int temp;
        temp=node.x+node.y;
       // printf("hash1111=");node.out();
        vector<HASH>::iterator it;
        for(it=hash[temp].begin();it!=hash[temp].end();++it){
            if(it->x==node.x && it->y==node.y){
                if(it->s<=node.s) return 1;
                else {
                    it->s=node.s;
                    return 0;
                }
            }
        }
        hash[temp].push_back(HASH(node.x,node.y,node.s));
       // printf("hash=");node.out();
        return 0;
    }
    
    int gcd(int a,int b){
        for(int t;t=b;b=a%b,a=t);
        return a;
    }
    
    bool gao(NODE &node){
       // node.out();
        if(node.x==n || node.y==n){
            printf("%d\n",node.s);
            return 1;
        }
        if(node.x<node.y) swap(node.x,node.y);
       // printf("temp: "); node.out();
        if(node.x<=0 || node.y<0 || (node.y==0 && node.x>n) || node.x==node.y || (node.x>n && node.y>n) || node.x>=2*n
            || n%gcd(node.x,node.y) || gaoh(node)) return 0;
        cal(node);
        pq.push(node);
        return 0;
    }
    
    int main(){
      //  freopen("aa.in","r",stdin);
      //  freopen("aa.out","w",stdout);
        int i,x,y,s;
        while(scanf("%d",&n)!=EOF){
            while(!pq.empty()) pq.pop();
            for(i=0;i<maxn;++i) hash[i].clear();
            if(n==1){
                printf("0\n");
                continue;
            }
            next=NODE(1,0,0);
            gaoh(next);
            cal(next);
            pq.push(next);
            while(!pq.empty()){
                now=pq.top();
                pq.pop();
                x=now.x,y=now.y,s=now.s+1;
              //  now.out();
                next=NODE(x+x,y,s);if(gao(next)) break;
                next=NODE(x+x,x,s);if(gao(next)) break;
                next=NODE(x+y,y,s);if(gao(next)) break;
                next=NODE(x,x+y,s);if(gao(next)) break;
                next=NODE(x,y+y,s);if(gao(next)) break;
                next=NODE(y+y,y,s);if(gao(next)) break;
                next=NODE(x-y,y,s);if(gao(next)) break;
                next=NODE(x,y-x,s);if(gao(next)) break;
                next=NODE(x,x-y,s);if(gao(next)) break;
                next=NODE(y,y-x,s);if(gao(next)) break;
            }
        }
        return 0;
    }

    poj2337

    Fleury算法求欧拉路

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define maxn 1010
    bool h[30];
    char sstr[maxn][22],*str[maxn];
    int start[maxn],end[maxn];
    int vis[maxn];
    int l[30],r[30];
    int rd[30],cd[30];
    int n,des;
    struct cmp
    {
        bool operator () (const char *a, const char *b)
        {
            return strcmp(a, b)<0;
        }
    };
    int fa[30];
    int find(int x){
        if(x!=fa[x]) fa[x]=find(fa[x]);
        return fa[x];
    }
    int gao(int p,int have){
        if(have==n){
            des=p;
            return 1;
        }
        int i,next=end[p];
        for(i=l[next];i<r[next];++i){
            if(vis[i]==-1){
                vis[i]=p;
                if(gao(i,have+1)) return 1;
                vis[i]=-1;
            }
        }
        return 0;
    }
    int ans[maxn];
    int main(){
       // freopen("test.in","r",stdin);
        int T,i,no,cnt,se;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(i=0;i<26;++i) l[i]=r[i]=rd[i]=cd[i]=0,fa[i]=i;
            for(i=0;i<n;++i){
                scanf("%s",sstr[i]);
                str[i]=sstr[i];
            }
            sort(str,str+n,cmp());
            memset(h,0,sizeof(h));
            for(i=0;i<n;++i){
                start[i]=str[i][0]-'a';
                end[i]=str[i][strlen(str[i])-1]-'a';
                ++cd[start[i]];
                ++rd[end[i]];
                fa[find(start[i])]=find(end[i]);
                h[start[i]]=h[end[i]]=1;
                if(start[i]!=start[i-1]){
                    r[start[i-1]]=i;
                    l[start[i]]=i;
                }
            }
            r[start[i-1]]=i;
        //  for(i=0;i<n;++i) printf("%s\n",str[i]);
            int tot=0;
            for(i=0;i<26;++i)
                if(h[i] && find(i)==i) ++tot;
            if(tot>1){
                printf("***\n");
                continue;
            }
            cnt=0,no=0;
            for(i=0;i<26;++i){
                if(rd[i]-cd[i]>1 || cd[i]-rd[i]>1){
                    no=1;
                    break;
                }
                if(rd[i]-cd[i]==1){
                    ++cnt;
                }
                else if(cd[i]-rd[i]==1){
                    ++cnt;
                    se=i;
                }
            }
          // printf("no=%d cnt=%d\n",no,cnt);
            if(no || cnt>2) {
                printf("***\n");
                continue;
            }
            memset(vis,0xff,sizeof(vis));
            if(!cnt){
                vis[0]=-2;
                gao(0,1);
            } else{
                for(i=l[se];i<r[se];++i){
                    vis[i]=-2;
                    if(gao(i,1)) break;
                    vis[i]=-2;
                }
            }
            cnt=0;
            int Des=des;
           do{
                ans[cnt++]=des;
                des=vis[des];
            } while(des!=-2);
          //  for(i=0;i<cnt;++i) printf("ansi=%d\n",ans[i]);
            for(i=cnt-1;i>0;--i) printf("%s.",str[ans[i]]);
            printf("%s\n",str[ans[i]]);
        }
        return 0;
    }

    poj2186

    求强连通分量后缩点,判唯一的出度为0的点的原始点数

    #include<cstdio>
    #include<cstring>
    #include<stack>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define maxn 10010
    vector<int> adj[maxn];
    int dfn[maxn],low[maxn],d[maxn],scc[maxn];
    int tot,n,m,cnt;
    stack<int> s;
    void gao(int u){
        int v;
        dfn[u]=low[u]=++tot;
        s.push(u);
        vector<int>::iterator it;
        for(it=adj[u].begin();it!=adj[u].end();++it){
            v=*it;
            if(!dfn[v]) gao(v);
            low[u]=min(low[u],low[v]);
        }
        if(low[u]==dfn[u]){
            ++cnt;
            while(!s.empty()){
                v=s.top();
                scc[v]=cnt;
                s.pop();
                if(low[v]==dfn[v]) break;
            }
        }
    }
    int main(){
        int u,v,i,z=0,ans,p;
        vector<int>::iterator it;
        scanf("%d%d",&n,&m);
        while(m--){
            scanf("%d%d",&u,&v);
            adj[u].push_back(v);
        }
        for(i=1;i<=n;++i)
            if(!dfn[i]) gao(i);
        for(i=1;i<=n;++i){
            for(it=adj[i].begin();it!=adj[i].end();++it){
                if(scc[i]!=scc[*it]) ++d[scc[i]];
            }
        }
        for(i=1;i<=cnt;++i)
            if(!d[i]) ++z,p=i;
        if(z>1 || !z) printf("0\n");
        else{
            ans=0;
            for(i=1;i<=n;++i)
                if(scc[i]==p) ++ans;
            printf("%d\n",ans);
        }
        return 0;
    }

    poj1944

    枚举弃边,跳表统计数量

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    #define maxn 1010
    #define maxp 10010
    int n,p;
    int x[maxp],y[maxp];
    int f[maxn];
    void swap(int &a,int &b){
        int t=a;
        a=b;
        b=t;
    }
    int main(){
        int i,ans,j,temp,far;
        scanf("%d%d",&n,&p);
        ans=n;
        for(i=0;i<p;++i){
            scanf("%d%d",&x[i],&y[i]);
            if(x[i]==y[i]){
                --i,--p;
            }else if(x[i]>y[i]){
                swap(x[i],y[i]);
            }
        }
        for(i=1;i<=n;++i){
            memset(f,0,sizeof(f));
            for(j=0;j<p;++j){
                if(x[j]>=i+1 || y[j]<=i){
                    f[x[j]]=max(y[j],f[x[j]]);
                }else{
                    f[y[j]]=n+1;
                    f[1]=max(x[j],f[1]);
                }
            }
            temp=0;
            far=1;
            for(j=1;j<=n;++j){
                if(f[j]>far){
                    temp+=f[j]-max(far,j);
                    far=f[j];
                }
            }
            ans=min(temp,ans);
        }
        printf("%d\n",ans);
        return 0;
    }


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值