• 几道图论题的一句话题解


    CF118E Bertown roads

    Codeforces 118E Bertown roads

    题意:无向连通图,给边定向,使其强连通。

    题解:DFS,树边向下连,返祖边向上连,注意判断无解。

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){ int x;scanf("%d",&x);return x; }
    const int N=1e5+10,M=6e5+10;
    struct bian{
        int l,e,n;
    };
    bian b[M];
    int s[N],tot=1;
    void add(int x,int y){
        tot++;
        b[tot].e=y;
        b[tot].n=s[x];
        s[x]=tot;
    }
    
    bool vis[N];
    int nfd[N],dfnn=0;
    void ss0(int x){
        vis[x]=1;
        for(int i=s[x];i;i=b[i].n){
            if(vis[b[i].e]){ if(!b[i^1].l) b[i].l=1; continue; }
            b[i].l=1;
            ss0(b[i].e);
        }
    }
    void ss1(int x){
        vis[x]=1;
        for(int i=s[x];i;i=b[i].n){
            if(b[i].l)continue;
            if(vis[b[i].e])continue;
            ss1(b[i].e);
        }
    }
    
    int main(){
        int n=getint(),m=getint();
        for(int i=0;i<m;i++){
            int x=getint(),y=getint();
            add(x,y);
            add(y,x);
        }
        ss0(1);
        memset(vis,0,sizeof(bool)*(n+2));
        ss1(1);
        bool ok=1;
        for(int i=1;i<=n;i++)if(!vis[i])ok=0;
        if(!ok)puts("0");
        else for(int i=1;i<=n;i++)for(int j=s[i];j;j=b[j].n)if(b[j].l)printf("%d %d
    ",i,b[j].e);
    }
    
    

    CF231E Cactus

    Codeforces 231E Cactus

    题意:给定一点仙人掌,多次询问 (u)(v) 的简单路径数量。

    题解:每个环会让答案 ( imes 2);于是把环缩成点,询问即在树上统计链上有多少环缩成的点。

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){ int x;scanf("%d",&x);return x; }
    const int N=2e5+10,M=4e5+10;
    struct bian{
        int l,e,n;
    };
    bian b[M];
    int s[N],tot=1;
    void add(int x,int y){
        tot++;
        b[tot].e=y;
        b[tot].n=s[x];
        s[x]=tot;
    }
    int v[N];
    int col[N];
    
    namespace Graph{
    
    bian b[M];
    int s[N],tot=1;
    void add(int x,int y){
        tot++;
        b[tot].e=y;
        b[tot].n=s[x];
        s[x]=tot;
    }
    int stk[N],top;
    bool vis[N];
    bool instk[N];
    int cnt;
    void ss(int x,int fa){
        stk[top++]=x;
        instk[x]=1;
        vis[x]=1;
        for(int i=s[x];i;i=b[i].n){
            int v=b[i].e;
            if(i==(fa^1))continue;
            if(!vis[v])ss(v,i);
            if(instk[v]){
                ++cnt;
                while(stk[top]!=v){
                    --top;
                    col[stk[top]]=cnt;
                }
                ::v[cnt]++;
            }
        }
        instk[x]=0;
        if(!col[x])col[x]=++cnt,--top;
    //    cerr<<x<<"! ";for(int i=0;i<top;i++)cerr<<" "<<stk[i];cerr<<endl;
    }
    
    } // namespace Graph
    
    const int L=18;
    int f[L][N],dep[N];
    bool vis[N];
    void ss(int x,int fa){
        vis[x]=1;
        for(int i=s[x];i;i=b[i].n){
        	int v=b[i].e;
            if(vis[v])continue;
            ::v[v]+=::v[x];
            dep[v]=dep[x]+1;
            f[0][v]=x;
            ss(b[i].e,x);
        }
    }
    void init_lca(int n){
        for(int i=1;i<L;i++)
            for(int j=1;j<=n;j++)f[i][j]=f[i-1][f[i-1][j]];
    }
    int lca(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        for(int i=L-1;i>=0;i--)if(dep[f[i][x]]>=dep[y])x=f[i][x];
        if(x==y)return x;
        for(int i=L-1;i>=0;i--)if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
        return f[0][x];
    }
    int query(int x,int y){
        int l=lca(x,y);
        return v[x]+v[y]-v[l]-v[f[0][l]];
    }
    int p2[N];
    
    int main(){
        int n=getint(),m=getint();
        for(int i=0;i<m;i++){
            int x=getint(),y=getint();
            Graph::add(x,y);
            Graph::add(y,x);
        }
        Graph::ss(1,0);
        for(int i=1;i<=n;i++)for(int j=Graph::s[i];j;j=Graph::b[j].n)
            add(col[i],col[Graph::b[j].e]),
            add(col[Graph::b[j].e],col[i]);
        dep[1]=1;
        ss(1,0);
        p2[0]=1;
        for(int i=1;i<=n;i++)p2[i]=p2[i-1]*2ll%1000000007;
        n=Graph::cnt;
        init_lca(n);
        int q=getint();
        while(q--){
            int x=getint(),y=getint();
            printf("%d
    ",p2[query(col[x],col[y])]);
        }
    }
    
    

    CF412D Giving Awards

    Codeforces 412D Giving Awards

    题意:给定一有向图,保证没有反向平行边,求其补图的哈密顿回路。

    题解:DFS 树上的后序遍历。

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){ int x;scanf("%d",&x);return x; }
    const int N=1e5+10,M=6e5+10;
    struct bian{
        int l,e,n;
    };
    bian b[M];
    int s[N],tot=0;
    void add(int x,int y){
        tot++;
        b[tot].e=y;
        b[tot].n=s[x];
        s[x]=tot;
    }
    
    bool vis[N];
    void ss(int x){
        vis[x]=1;
        for(int i=s[x];i;i=b[i].n){
            if(vis[b[i].e])continue;
            ss(b[i].e);
        }
        printf("%d ",x);
    }
    
    int main(){
        int n=getint(),m=getint();
        for(int i=0;i<m;i++){
            int x=getint(),y=getint();
            add(x,y);
        }
        for(int i=1;i<=n;i++)if(!vis[i])ss(i);
    }
    

    CF858F Wizard's Tour

    codeforces 858F Wizard's Tour

    题意:将无向图的编辑化为多个 ((u,v),(v,w))

    题解:DFS,贪心,可能多余出来的一条边留给父亲。

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){ int x;scanf("%d",&x);return x; }
    const int N=2e5+10,M=4e5+10;
    struct bian{
        int l,e,n;
    };
    bian b[M];
    int s[N],tot=1;
    void add(int x,int y){
        tot++;
        b[tot].e=y;
        b[tot].n=s[x];
        s[x]=tot;
    }
    
    vector<tuple<int,int,int> >v;
    bool vis[N];
    void ss(int x,int fa){
        vis[x]=1;
        int lst=0;
        for(int i=s[x];i;i=b[i].n){
            if(i==(fa^1))continue;
            if(!vis[b[i].e])ss(b[i].e,i);
            if(!b[i].l){
                if(lst){
                    b[i].l=1; b[i^1].l=1;
                    b[lst].l=1; b[lst^1].l=1;
                    v.emplace_back(b[lst].e,x,b[i].e);
                    lst=0;
                }else lst=i;
            }
        }
        if(lst&&fa){
            b[fa].l=1; b[fa^1].l=1;
            b[lst].l=1; b[lst^1].l=1;
            v.emplace_back(b[lst].e,x,b[fa^1].e),lst=0;
        }
    }
    
    int main(){
        int n=getint(),m=getint();
        for(int i=0;i<m;i++){
            int x=getint(),y=getint();
            add(x,y);
            add(y,x);
        }
        for(int i=1;i<=n;i++)if(!vis[i])ss(i,0);
        printf("%d
    ",v.size());
        for(auto i:v)printf("%d %d %d
    ",get<0>(i),get<1>(i),get<2>(i));
    }
    
    

    洛谷 P5540 [BalkanOI2011] timeismoney | 最小乘积生成树

    P5540 [BalkanOI2011] timeismoney | 最小乘积生成树

    题意:无向图,每条边有权值 (a_i,b_i),求生成树,最小化 ((sum_i a_i) imes (sum_i b_i))

    题解:最优解一定在下凸包上,于是我们凸包上二分。具体地,我们令斜率为 (k),则令边权为 (ka+b) 并求 MST。

    #include<bits/stdc++.h>
    using namespace std;
    inline int getint(){
        int ans=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9'){
            ans=ans*10+c-'0';
            c=getchar();
        }
        return ans*f;
    }
    #define ll long long
    #define pii pair<int,int>
    #define fi first
    #define se second
    const int N=200,M=10010;
    struct bian{
        int s,t,x,y;
    };
    bian b[M];
    int n,m;
    double k1,k2;
    inline bool operator<(bian a,bian b){
        return a.x*k1+a.y*k2<b.x*k1+b.y*k2;
    }
    int f[N];inline int _(int x){ return x==f[x]?x:f[x]=_(f[x]); }
    inline ll abs(pii p){
        return p.fi*1ll*p.se;
    }
    inline pii mst(double k1,double k2){
        ::k1=k1;::k2=k2;
        sort(b,b+m);
        for(int i=0;i<=n;i++)f[i]=i;
        pii ans;
        int cnt=0;
        for(int i=0;i<m;i++){
            int x=_(b[i].s),y=_(b[i].t);
            if(x==y)continue;
            ans.fi+=b[i].x;
            ans.se+=b[i].y;
            f[x]=y;
            ++cnt;
            if(cnt==n-1)break;
        }
        return ans;
    }
    inline pii solve(pii p,pii q,int dep=0){
        pii ans=abs(p)<abs(q)?p:q;
        if(p.fi==q.fi||p.se==q.se)return ans;
        double k=(q.se-p.se*1.0)/(p.fi-q.fi);
        pii r=mst(k,1);
        //cerr<<string(dep,' ')<<"solve "<<p.fi<<" "<<p.se<<" "<<q.fi<<" "<<q.se<<"  "<<r.fi<<" "<<r.se<<"  "<<ans<<endl;
        if(r.fi*k+r.se-
           q.fi*k-q.se>-1e-8)return ans;
        pii t=solve(r,p,dep+1);
        ans=abs(ans)<abs(t)?ans:t;
        t=solve(q,r,dep+1);
        ans=abs(ans)<abs(t)?ans:t;
        return ans;
    }
    inline pii solve(){
        pii p1,p2;
        p1=mst(1,0);
        p2=mst(0,1);
        if(p1.fi<0||p2.se<0)return pii(0,0);
        return solve(p1,p2);
    }
    int main(){
        n=getint(),m=getint();
        for(int i=0;i<m;i++)b[i].s=getint(),b[i].t=getint(),b[i].x=getint(),b[i].y=getint();
        pii ans=solve();
    
        cout<<ans.first<<" "<<ans.second<<endl;
    }
    
    
    知识共享许可协议
    若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
  • 相关阅读:
    Python
    git SSL certificate problem: unable to get local issuer certificate
    Chapter 1 Securing Your Server and Network(13):配置端点安全性
    例说linux内核与应用数据通信系列
    Android 学习历程摘要(三)
    线程调度策略SCHED_RR(轮转法)和SCHED_FIFO(先进先出)之对照
    内核工作队列【转】
    android 电池(三):android电池系统【转】
    android 电池(二):android关机充电流程、充电画面显示【转】
    android 电池(一):锂电池基本原理篇【转】
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/14623362.html
Copyright © 2020-2023  润新知