• 20170824图论选讲部分习题


    1.车站分级

    讲过啊,拓扑排序,每个停靠的车站向所有未停靠的车站连一条边,拓扑层数即可,小优化,每次删0度点的边时顺便统计一下删好后为0度点的边

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define maxn 1005
    using namespace std;
    int to[maxn][maxn],point[maxn],Map[maxn][maxn],x[maxn],v[maxn],a[maxn],b[maxn];
    int ans=0,n,m;
    void work()
    {
        for(int i=1;i<=n;i++)
        if(!v[i]) point[++point[0]]=i;
        while(point[0])
        {
            ans++;
            while(point[0])
            {
                int k=point[point[0]];point[0]--;
                for(int i=1;i<=to[k][0];i++)
                {
                    v[to[k][i]]--;
                    if(!v[to[k][i]]) x[++x[0]]=to[k][i];
                }
            }
            for(int i=1;i<=x[0];i++)
            point[i]=x[i];
            point[0]=x[0];
            x[0]=0;
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&a[0]);
            b[0]=0;
            for(int i=1;i<=a[0];i++) scanf("%d",&a[i]);
            for(int i=1;i<a[0];i++)
                for(int j=a[i]+1;j<a[i+1];j++)
                b[++b[0]]=j;
            for(int i=1;i<=a[0];i++)
                for(int j=1;j<=b[0];j++)
                if(!Map[a[i]][b[j]])
                {
                    Map[a[i]][b[j]]=1;
                    v[b[j]]++;
                    to[a[i]][++to[a[i]][0]]=b[j];
                }    
        }
        work();
    }

    2.种树,这个我写过题解了

    3.秦始皇的国家道路。先枚举选的是那条边,因为cnt总值最小肯定更优,我们用Prim求最小生成树可以接近最优值,考虑到加上选的边后的最小生成树是由原最小生成树换1条边的正确性可由Kruskal来证明吧。就是把最小生成树中u,v中的那条路径中最大的一条边换成枚举的那条边。

    #include<cstdio> 
    #include<cmath> 
    #include<algorithm> 
    using namespace std; 
    struct node{ 
        int x,y; 
        double val; 
    }a[2000005]; 
    int num1,num,f1,root; 
    int f[2000005],p[2000005],flag[2000005]; 
    double dis[1005][1005],x[2000005],y[2000005]; 
    int v[2000005],next[2000005],head[10005],vis[10005]; 
    double v1[2000005]; 
    int find(int u) 
    { 
        if (f[u]!=u) f[u]=find(f[u]); 
        return f[u]; 
    } 
    void add(int a,int b,double val) 
    { 
        num1++; 
        v[num1]=b; 
        v1[num1]=val; 
        next[num1]=head[a]; 
        head[a]=num1; 
    } 
    bool cmp(node a,node b) 
    { 
        return a.val<b.val; 
    } 
    void dfs(int u,double val) 
    { 
        dis[root][u]=val; 
        vis[u]=f1; 
        for (int i=head[u]; i; i=next[i]) 
        { 
            int V=v[i]; 
            if (vis[V]!=f1) dfs(V,max(val,v1[i])); 
        } 
    } 
    int main() 
    { 
    int asdasdasdasd;
        int t; 
        scanf("%d",&t); 
        while (t--) 
        { 
            num1=0; 
            num=0; 
            int n; 
            scanf("%d",&n); 
            for (int i=1; i<=n; i++) 
                head[i]=0; 
            for (int i=1; i<=n; i++) 
                scanf("%lf%lf%d",&x[i],&y[i],&p[i]); 
            for (int i=1; i<=n; i++) 
                for (int j=i+1; j<=n; j++) 
                { 
                    double dis=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); 
                    num++; 
                    a[num].x=i; 
                    a[num].y=j; 
                    a[num].val=sqrt(dis); 
                    /*num++; 
                    a[num].x=j; 
                    a[num].y=i; 
                    a[num].val=sqrt(dis);*/
                } 
            sort(a+1,a+num+1,cmp); 
            for (int i=1; i<=n; i++) 
                f[i]=i; 
            double ans=0; 
            for (int i=1; i<=num; i++) 
            { 
                flag[i]=0; 
                int fx=find(a[i].x); 
                int fy=find(a[i].y); 
                if (fx!=fy) 
                { 
                    f[fx]=fy; 
                    //f[fx]=find(fx); 
                    ans+=a[i].val; 
                    flag[i]=1; 
                } 
            } 
            for (int i=1; i<=num; i++) 
                if (flag[i])  
                { 
                    add(a[i].x,a[i].y,a[i].val); 
                    add(a[i].y,a[i].x,a[i].val); 
                } 
            f1=0; 
            for (int i=1; i<=n; i++) 
            { 
                f1++; 
                root=i; 
                dfs(i,0); 
            } 
            double ans1=0; 
            for (int i=1; i<=n; i++) 
                for (int j=i+1; j<=n; j++) 
                    if ((p[i]+p[j])/(ans-dis[i][j])>ans1) ans1=(p[i]+p[j])/(ans-dis[i][j]); 
            printf("%.2f
    ",ans1); 
        } 
        return 0; 
    } 
        

    4.受欢迎的奶牛

    Tarjan求强连通分量缩点

    求度为0的个数,如果大于等于2个,无解,不然输出度为0的强连通分量的size

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<stack> 
    #define maxn 100100
    using namespace std;
    stack<int> S;
    struct note{
        int u,v;
    }edge[maxn];
    bool instack[maxn];
    int to[maxn*2],id[maxn],Time,ans,num,sc,head[maxn],visit[maxn],next[maxn*2],low[maxn],dfn[maxn],n,m,size[maxn];
    void make_way(int u,int v)
    {
        to[++num]=v;
        next[num]=head[u];
        head[u]=num;
    }
    void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++Time;
        instack[u]=1;
        S.push(u);
        for(int ed=head[u];ed;ed=next[ed])
        {
            if(!dfn[to[ed]])
            {
                tarjan(to[ed],u);
                low[u]=min(low[u],low[to[ed]]);
            }else
            if(instack[to[ed]])
            low[u]=min(low[u],dfn[to[ed]]);
        }
        //cout<<u<<' '<<low[u]<<' '<<dfn[u]<<endl;
        if(low[u]==dfn[u])
        {
            sc++;
            int v;
            do{
                
                v=S.top();
                S.pop();
                instack[v]=0;
                id[v]=sc;
                size[sc]++; 
            }while(v!=u&&!S.empty());
        }
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d",&edge[i].u,&edge[i].v);
            make_way(edge[i].u,edge[i].v);
        }
        for(int i=1;i<=n;i++)
        if(!dfn[i])
        {
            tarjan(i,0);
        }
        for(int i=1;i<=m;i++)
        if(id[edge[i].u]!=id[edge[i].v])
        visit[id[edge[i].u]]++;
        bool flag=0;
        for(int i=1;i<=sc;i++)
        {
            if(!visit[i])
            {
                if(flag)
                {    
                    cout<<0<<endl;
                    return 0;
                }
                flag=1;
                ans=i;
            }
        }
        printf("%d
    ",size[ans]);
     } 

    6.矿场搭建

    WA10分,待改

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    #define ll long long
    using namespace std;
    int n,m,cnt,num,tot,son_num,ans1,Time,T,cases,root;
    ll ans2;
    int head[500005],dfn[500500],low[500005],vis[500005];
    bool cut[500005];
    int Next[1000005],to[1000005];
    void make_way(int u,int v)
    {
        to[++num]=v;
        Next[num]=head[u];
        head[u]=num;
     } 
     void tarjan(int u,int fa_edge)
     {
         low[u]=dfn[u]=++Time;
         for(int edge=head[u];edge;edge=Next[edge])
         if(edge^1!=fa_edge)
         {
             int v=to[edge];
             if(!dfn[v])
             {
                 tarjan(v,u);
                 low[u]=min(low[u],low[v]); 
                 if(low[v]>=dfn[u])
                 {
                     if(u==root) son_num++;else cut[u]=1;
                 }
             }else
            {
                low[u]=min(low[u],dfn[v]);
             } 
         }
     }
     void dfs(int u)
     {
         vis[u]=T;
         if(cut[u]) return;
         cnt++;
         for(int edge=head[u];edge;edge=Next[edge])
         {
             if(cut[to[edge]]&&vis[to[edge]]!=T) num++,vis[to[edge]]=T;
             if(!vis[to[edge]]) dfs(to[edge]);
         }
      } 
    int main()
    {
        int Case=0;
        while(~scanf("%d",&m)&&m)
        {
            Case++;
            memset(head,0,sizeof(head));
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            memset(low,0,sizeof(low));
            memset(cut,0,sizeof(cut));
            Time=num=n=ans1=T=0;
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d %d",&u,&v);
                n=max(n,max(u,v));
                make_way(u,v);
                make_way(v,u);
            }
            for(int i=1;i<=n;i++)
            {
                if(!dfn[i])tarjan(root=i,0);
                if(son_num>=2)
                cut[root]=1;
                son_num=0;
            }
            ans1=0;
            ans2=1;
            for(int i=1;i<=n;i++)
                if(!vis[i]&&!cut[i])
                {
                    T++;cnt=num=0;
                    dfs(i);
                    if(!num) ans1+=2,ans2*=cnt*(cnt-1)/2;
                    if(num==1) ans1++,ans2*=cnt;
                }
            printf("Case %d: %d %lld
    ",Case,ans1,ans2);
        }
        
    }
  • 相关阅读:
    理解CSS中BFC
    js 异步执行顺序
    javascript中继承方式及优缺点(三)
    javascript中继承方式及优缺点(二)
    javascript中继承方式及优缺点(一)
    javascript中的原型和原型链(五)
    javascript中的原型和原型链(四)
    javascript中的原型和原型链(三)
    跨域问题及解决思路
    lambda表达式之方法引用
  • 原文地址:https://www.cnblogs.com/dancer16/p/7436589.html
Copyright © 2020-2023  润新知