zoukankan      html  css  js  c++  java
  • HZNU Training 23 for Zhejiang Provincial Competition 2020

    C - C

     CodeForces - 653D 

     网络流,待补。

    F - F

     HDU - 2647 

     拓扑排序,从上往下回溯,挺好奇差分约束为啥就不对。拓扑排序有明显的优先级。

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef double db;
    const int N=1e4+50;
    vector<int>e[N];
    int n,m;
    int in[N],a[N];
    int topo(){
        int cnt=0;
        queue<int>Q;
        for(int i=1;i<=n;i++)if(in[i]==0)cnt++,Q.push(i);
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=0;i<e[u].size();i++){
                int v=e[u][i];--in[v];
                if(!in[v]){
                    Q.push(v),cnt++;
                    a[v]=max(a[v],a[u]+1);
    
                }
            }
        }
        if(cnt<n)return -1;
        int sum=0;
        for(int i=1;i<=n;i++)sum+=888+a[i];
        return sum;
    }
    int main(){
    
        while(~scanf("%d %d",&n,&m)){
        memset(in,0,sizeof in);
        memset(a,0,sizeof a);
        for(int i=1;i<=n;i++)e[i].clear();
        for(int i=1,u,v;i<=m;i++){
            scanf("%d %d",&u,&v);
            e[v].pb(u);in[u]++;
        }    
        cout<<topo()<<endl;
        }
        // system("pause");
        return 0;
    }
    View Code

    G - G

     HDU - 3635 

    带权并查集,维护一个sum数组,和move数组,

    当移动时,把两堆移到一起,

    查询时,找出当前节点的根,记录次数。

    这样维护一个并查集,根节点move必然为0.

    然后一个点的移动次数必然是到根节点的路径次数和。

    然后每次find其实就是把当前节点和根接到一起。

    #include<cstdio>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef double db;
    const int N=1e4+50;
    int fa[N],sum[N],move[N];
    int n;
    void init(){
    
        for(int i=1;i<=n;i++)fa[i]=i,move[i]=0,sum[i]=1;
    
    }
    
    int find(int x){
        if(fa[x]==x)return x;
        else {
            int t=fa[x];
        fa[x]=find(fa[x]);
        move[x]+=move[t];
    
        return fa[x];
        }
    }
    
    void build(int u,int v){
        int du=find(u);
        int dv=find(v);
        if(du!=dv){
            fa[du]=dv;
            sum[du]=sum[dv]=sum[du]+sum[dv];
            move[du]++;
    
        }
    
    }
    int main(){
        int t,q,cas=0;
        char op;
        scanf("%d",&t);
        while(t--){
            scanf("%d %d",&n,&q);
            printf("Case %d:
    ",++cas);
            init();
    
            for(int i=1,u,v;i<=q;i++){
                getchar();
            scanf("%c",&op);
    
            if(op=='T'){
                scanf("%d %d",&u,&v);
                build(u,v);
            }
    
            else {
    
                scanf("%d",&u);
                int du=find(u);
                printf("%d %d %d
    ",du,sum[du],move[u]);
            }
    
            }
    
        }
        // system("pause");
        return 0;
    }
    View Code 

    H - H

     计蒜客 - A1542 

    对于一个给定的图,最小点覆盖等于最大匹配,最大独立集等于最小点覆盖,题目让求最大独立集,实际上就是最大匹配。

    先用floyd求闭包,然后求一遍最大匹配,每次找增广路是match[ v ],

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef double db;
    const int N=1e2+50;
    int gp[N][N];
    int match[N],vis[N];
    int n,m;
    void floyd(){
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    gp[i][j]|=gp[i][k]&gp[k][j];
                }
            }
        }
    }
    bool findpath(int u){
        for(int i=1;i<=n;i++){
            if(gp[u][i]&&!vis[i]){
               vis[i]=1;
                if(!match[i]||findpath(match[i])){
                    match[i]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    void init(){
        memset(gp,0,sizeof gp);
        memset(match,0,sizeof match);
        // for(int i=1;i<=n;i++){
        //     for(int j=1;j<=n;j++){
        //         gp[i][j]=0;
        //         match[i]=0;
        //     }
        // }
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d %d",&n,&m);
            init();
            for(int i=1,u,v;i<=m;i++){
                scanf("%d %d",&u,&v);
                gp[u][v]=1;
            }
            floyd();
            int sum=0;
            for(int i=1;i<=n;i++){
                memset(vis,0,sizeof vis);
                if(findpath(i))sum++;
            }
            printf("%d
    ",n-sum);
        }
        // system("pause");
        return 0;
    }
    View Code

     

    L - L

     POJ - 2349 

    对于一颗给定的最小生成树,当你选择s个点使得他们之间互相联通时,实际上会去掉 s -1 条边,贪心取最大即可。

    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define pb push_back
    const int N=5e2+50;
    typedef double db;
    // db eps=1e-9;
    int fa[N];
    struct point{db x,y;}P[N];
    struct edge{
        int u,v;db w;
        edge(int a,int b,db c){
            u=a;v=b;w=c;
        }
    };
    vector<edge>e,ans;
    db dis(point a,point b){return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) );}
    bool cmp(edge a,edge b){
        return a.w<b.w;
    }
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void build(int x,int y){int dx=find(x),dy=find(y);if(dx!=dy)fa[dx]=dy;}
    int s,n;
    void init(){
        for(int i=1;i<=n;i++)fa[i]=i;
        e.clear();ans.clear();
    }
    void solve(){
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                db d=dis(P[i],P[j]);
                e.pb(edge(i,j,d));
            }
        }
        sort(e.begin(),e.end(),cmp);
        for(int i=0;i<e.size();i++){
            int u=e[i].u,v=e[i].v;
            // db w=e[i].w;
            if(find(u)==find(v))continue;
            build(u,v);
            ans.pb(e[i]);
        }
        // for(int i=0;i<ans.size();i++)cout<<ans[i].w<<endl
        // cout<<ans.size()<<endl;
        sort(ans.begin(),ans.end(),cmp);
        if(n-s-1>=0)printf("%.2lf
    ",ans[n-s-1].w);
        else printf("%.2lf",0);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d %d",&s,&n);
            init();
            for(int i=1;i<=n;i++)scanf("%lf %lf",&P[i].x,&P[i].y);
            
            solve();
        }
    
        // system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    白手起家的亿万富翁马克·库班,既是球队老板又是知名投资人
    放弃事业单位工作,他投身智能产品研发,开办三百家线下体验店
    从一名资深“吃货”到成为59家餐饮店老板,看他怎么成功转变的
    从餐厅的小小服务员成长为中式快餐创始人,看他如何逆袭的
    从摆摊开始,发展成坐拥十多家分店的企业家,看他如何蜕变的
    perl 2维数组转json
    获取 指定pool的成员状态,返回2维数组
    民生银行牛新庄:大数据及分布式技术在银行系统中实践应用
    Mockjs+Ajax实践
    Mockjs+Ajax实践
  • 原文地址:https://www.cnblogs.com/littlerita/p/12748812.html
Copyright © 2011-2022 走看看