zoukankan      html  css  js  c++  java
  • 18寒假第七测

    又回学校了,╮(╯▽╰)╭

    第一题:由于城市群之间的距离是相同的特性,根据网络流想到增点,用一个新点代表一个城市群,注意判断出边和入边,我是用二维dis表示出入+SPFA

    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define INF 1000000008
    const int maxn = 4e5+5;
    struct edge{
        int to,co;
    };
    
    vector <edge> G[maxn];
    bool inq[maxn];
    int dis[maxn][2];
    void read(int &x){
        int f=1;x=0;char s=getchar();
        while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
        x*=f;
    }
    int n,m,m1,m2,s,t;
    void SPFA(int s){
        queue <int> Q;
        Q.push(s);
        dis[s][0] = 0;
        inq[s] = 1;
        
        while(!Q.empty()){
            int u = Q.front();
            Q.pop();
            inq[u] = 0;
            for(int i = 0; i < (int)G[u].size(); i++){
                edge &e = G[u][i];
                int x = 0,y = 0;
                if(u>n&&e.to>n)y=1;
                if(u>n&&e.to<=n)x=1;
                if(dis[e.to][y] > dis[u][x] + e.co){
                    dis[e.to][y] = dis[u][x] + e.co;
                    if(!inq[e.to])Q.push(e.to), inq[e.to] = 1;
                }    
    
                
            }
        }
    }
    int main(){
        freopen("map.in","r",stdin);
        freopen("map.out","w",stdout);
        
        read(n),read(m);
        int N = 1+n+m;
        for(int i = 1+n; i < N; i++){
            int u, k;
            read(k);
            while(k--){
                read(u);
                G[i].push_back((edge){u,0});
                G[u].push_back((edge){i,0});
            }
        }
        read(m1);
        while(m1--){
            int u,v,w;
            read(u),read(v),read(w);
            G[u].push_back((edge){v,w});
            G[v].push_back((edge){u,w});
        }
        read(m2);
        while(m2--){
            int u,v,w;
            read(u),read(v),read(w);
            G[u+n].push_back((edge){v+n,w});
            G[v+n].push_back((edge){u+n,w});
        }
        read(s),read(t);
        for(int i = 1; i <= N; i++)
            dis[i][0] = dis[i][1] = INF;
        SPFA(s);
        if(dis[t][0] == INF&& dis[t][1] == INF)cout<<-1<<endl;
        else cout<<min(dis[t][0], dis[t][1])<<endl;
            
    }

    标答是建一个出点和一个入点+dijstra

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <map>
    #include <set>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 60010;
    const int maxm = 320010;
    
    struct edge
    {
        int u,v,next,w;
    }e[maxm];
    int h[maxn],num;
    long long dis[maxn];
    int n,m,m1,m2;
    struct node
    {
        int a,b;
    };
    
    void build(int u,int v,int w)
    {
        num++;
        e[num].u = u;
        e[num].v = v;
        e[num].w = w;
        e[num].next = h[u];
        h[u] = num;
    }
    
    typedef pair<long long,int>P;
    priority_queue<P,vector<P>,greater<P> >q;
    long long inf;
    
    long long dij(int s,int t)
    {
        int u,v;
        memset(dis,60,sizeof(dis));
        inf  = dis[t];
        dis[s] = 0;
        q.push(P(0,s));
        while(!q.empty())
        {
            P p = q.top();
            u = p.second;
            q.pop();
            if(dis[u] < p.first)
                continue;
            for(int i = h[u]; i; i = e[i].next)
            {
                v = e[i].v;
                if(dis[v] > dis[u] + e[i].w)
                {
                    dis[v] = dis[u] + e[i].w;
                    q.push(P(dis[v],v));
                }
            }
        }
        return dis[t];
    }
    
    int main()
    {
        freopen("map.in","r",stdin);
        freopen("map.out","w",stdout);
        cin >> n >> m;
        for(int i = 1; i <= m; i++)
        {
            int k,u;
            scanf("%d",&k);
            while(k--)
            {
                scanf("%d",&u);
                build(n+i+m,u,0);
                build(u,n+i,0);
            }
        }
        cin >> m1;
        for(int i = 1; i <= m1; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            build(u,v,w);
            build(v,u,w);
        }
        cin >> m2;
        for(int i = 1; i <= m2; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            build(u+n,v+n+m,w);
            build(v+n,u+n+m,w);
        }
        int s,t;
        scanf("%d%d",&s,&t);
        long long ans = dij(s,t);
        if(ans == inf)
            printf("-1
    ");
        else
            printf("%lld
    ",ans);
        return 0;
    }

    第二题 解析见第一测最后一题,一定要注意tarjan里面弹栈

    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<vector>
    using namespace std;
    const int maxn = 30005;
    void read(int &x){
        int f=1;x=0;char s=getchar();
        while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
        x*=f;
    }
    
    int dfn[maxn],low[maxn],idx,scc[maxn],scccnt;
    int t[maxn],top,r[maxn];
    bool ins[maxn];
    vector <int> G[maxn], g[maxn];
    void tarjan(int s){
        dfn[s] = low[s] = ++idx;
        t[++top] = s; ins[s] = 1;
        for(int i = 0; i < (int)G[s].size(); i++){
            int v = G[s][i];
            if(!dfn[v]){
                tarjan(v);
                low[s] = min (low[s], low[v]);
            }
            else if(ins[v])low[s] = min(low[s], dfn[v]);
        }
        
        if(low[s] == dfn[s]){
            scccnt++;
            int x = low[s];
            while(1){
                scc[t[top]] = scccnt;
                ins[t[top--]] = 0;
                if(t[top+1] == s)break;
            }
        }
    } 
    bool topsort(){
        queue <int> q;
        int cnt = 0;
        for(int i = 1; i <= scccnt; i++)
            if(!r[i])cnt++, q.push(i);
        if(cnt >= 2)return 0;
        while(!q.empty()){
            cnt = 0;
            int i = q.front();
            q.pop();
            for(int j = 0; j < g[i].size(); j++){
                int v = g[i][j];
                r[v]--;
                if(!r[v]){
                    q.push(v);
                    cnt++;
                }
            }
            if(cnt >= 2)return 0;
        }
            
        return 1;
    }
    int main(){
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        int T,n,m;
        read(T);
        while(T--){
            read(n),read(m);
            
            scccnt = idx = top = 0;
            memset(r,0,sizeof(r));
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(ins,0,sizeof(ins));
            memset(scc,0,sizeof(scc));
            for(int i = 1; i <= n; i++)
                G[i].clear(),g[i].clear();
                    
            for(int i = 1; i <= m; i++){
                int u, v;
                read(u),read(v);
                G[u].push_back(v);
            }
            for(int i = 1; i <= n; i++)
                if(!dfn[i])tarjan(i);
            for(int i = 1; i <= n; i++){
                int u = scc[i];
                for(int j = 0; j < (int)G[i].size(); j++){
                    int v = scc[G[i][j]];
                    if(u != v){
                        g[u].push_back(v);
                        r[v]++;
                    }
                }
            }
            if(topsort())printf("Yes
    ");
            else printf("No
    ");
        }
        
    }

    第三题 先一个裸地最小生成树,在对选择每个公司进行模拟(在新图上连边),还需要新连的边一定在原生成树的边中,正确性易见,这样复杂度从m*k变成了m*n;

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    #define INF 50000000000009LL 
    const int maxn = 30005;
    const int maxm = 200000+5;
    int f[maxn], a[maxn];
    struct edge { 
        int u,v,co;
     };
    edge G[maxm],N[maxm];
    vector <int> K[maxn];
    void read(int &x){
        int f=1;x=0;char s=getchar();
        while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
        x*=f;
    }
    int Find(int x){
        return f[x] == x ? x : f[x] = Find(f[x]);
    }
    void Union(int u,int v){
        int x = Find(u), y =Find(v);
        f[x]= y;
    }
    bool check(int u,int v){
        return Find(u) == Find(v);
    }
    bool cmp(edge a, edge b){
        return a.co < b.co;
    }
    int main(){
        freopen("airplane.in","r",stdin);
        freopen("airplane.out","w",stdout);
        int n, m, k, tot = 0, cnt = 0;
        long long ans = INF;
        int q = 0;
        read(n),read(m),read(k);
        for(int i = 1; i <= m ;i++)read(a[i]);
        for(int i = 1; i <= k; i++){
            int u, v, w, s;
            read(u),read(v),read(w),read(s);
            G[++tot]=(edge){u,v,w};
            G[++tot]=(edge){v,u,w};
            K[s].push_back(u);
            K[s].push_back(v);
        }
        
        sort(G+1, G+1+tot, cmp);
        for(int i = 1; i <= n; i++)f[i] = i;    
        for(int i = 1; i <= tot; i++){
            int u = G[i].u, v = G[i].v;
            if(!check(u, v)){
                Union(u, v);
                N[++q] = G[i];
            }
            if(q == n-1)break;
        }
        
        sort(N+1, N+1+q, cmp);
        for(int i = 1; i <= m; i++){
            long long money = 0;
            int p = 0, cnt = 0;
            
            for(int j = 1; j <= n; j++)f[j] = j;        
            for(int j = 0; j < (int)K[i].size(); j+=2){
                int u = K[i][j], v = K[i][j+1];
                if(!check(u, v)){
                    Union(u,v);
                    cnt++;
                }            
            }    
            cnt = n - 1 - cnt;
            for(int j = 1; j <= q; j++){
                int u = N[j].u, v = N[j].v;
                if(!check(u, v)){
                    Union(u, v);
                    money += N[j].co;
                    p++;
                }
                if(cnt == p)break;
            }
            ans = min(ans, (long long)money+a[i]);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    SqlServer 查看数据库中所有存储过程
    SqlServer 查看数据库中所有视图
    SqlServer 查询表的详细信息
    SqlServer 遍历修改字段长度
    net core 操作Redis
    Tuning SharePoint Workflow Engine
    Open With Explorer
    Download language packs for SharePoint 2013
    Change Maximum Size For SharePoint List Template when Saving
    Six ways to store settings in SharePoint
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8457484.html
Copyright © 2011-2022 走看看