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

    猪猪的想法
    输入文件:thought.in
    输出文件:thought.out
    时间限制:1 second
    空间限制:128 MB
    题目描述
    狗蛋养了许多只可爱的猪猪,这些猪猪她萌都有一些奇怪的想法:比如说猪猪喜欢猪猪,猪猪之间的喜欢是一
    个很有趣的事情——喜欢是可以传递的,例如猪猪A喜欢猪猪B,猪猪B喜欢猪猪C,那么可以说猪猪A喜欢猪猪C
    。有意思的一点是,她萌不喜欢自恋的猪猪,一旦出现了自恋的猪猪,那么极有可能的是这个团体出现危险。现在
    给你只猪猪对单方面的关系,请问这个只猪猪组成的团体是否危险呢?是输出Yes ,否输出No 。
    输入格式
    题目包含多组数据
    第一行一个数T,表示数据组数。
    对于每一组数据:
    第一行两个正整数n,m,表示有n只猪猪和m个单向关系。
    接下来行,每一行两个数表示的单向关系。
    输出格式
    共T行,每一行一个字母,表示结果。
    样例
    样例输入

    2
    2 2
    1 2
    2 1
    2 1
    1 2


    样例输出

    No
    Yes

    数据范围
    n <=10^6 , m <= n*(n-1)/2 ;

    题解:用拓扑看有没有环就好了,不过我用的tarjian,不过此题的一个点 指向自己的情况要注意

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int maxn = 100000 + 5;
    int n, m, top, t[maxn], dfn[maxn], low[maxn], cnt, idx, scccnt;
    bool ins[maxn];
    vector <int> G[maxn], scc[maxn]; 
    
    void tarjian(int u){
        dfn[u] = low[u] = ++idx;
        t[++top] = u;
        ins[u] = 1;
        
        for(int i = 0; i < G[u].size(); i++){
            int v = G[u][i];
            if(!dfn[v]){
                tarjian(v);
                low[u] = min(low[v], low[u]);
            }
            else if(ins[v])low[u] = min(low[u], dfn[v]);
        }
        
        if(dfn[u] == low[u]){
            int x = dfn[u];
            scccnt++;
            while(1){
                scc[scccnt].push_back(t[top]);
                ins[t[top--]] = 0;
           if(t[top+1]])break; } } }
    int main(){ freopen("thought.in","r",stdin); freopen("thought.out","w",stdout); int Q; scanf("%d",&Q); while(Q--){ memset(t, 0, sizeof(t)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(ins, 0, sizeof(ins)); top = idx = scccnt = cnt = 0; scanf("%d%d",&n,&m); for(int i = 1; i <= n + 1; i++) G[i].clear(), scc[i].clear(); for(int i = 1; i <= m; i++){ int u, v; scanf("%d%d",&u,&v); G[u].push_back(v); } for(int i = 1; i <= n; i++) if(!dfn[i])tarjian(i); for(int i = 1; i <= scccnt; i++){ if(scc[i].size() != 1)cnt++; } if(cnt)cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }


    最长的路径
    输入文件:dag.in
    输出文件:dag.out
    时间限制:1 second
    空间限制:128 MB
    题目描述
    给定一张个点条边的有向无环图,每个点有点权,问从出发,路径最长是多少。
    此处路径长度的定义为路径上的经过的点的点权和(包括起点和终点)。
    输入格式
    第一行包含n,m两个数。
    接下来一行个数,第i个数表示的点权wi。
    接下来行,每一行两个数表示的一条单向边。
    输出格式
    输出最长路径的长度。
    样例
    样例输入

    5 5
    1 2 3 4 5
    1 2
    2 3
    3 4
    4 5
    5 1
    样例输出

    15
    数据范围
    n <=10^5 , m <= n*(n-1)/2 ;

    题解:SPFA,用dijsktra要存负权,不能跑最大路

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<cstring>
    #define maxn 1000000 +5
    using namespace std;
    int n, m, S;
    struct edge{
        int to,co;
    };
    vector <edge> G[maxn];
    int dis[maxn], w[maxn], ans;
    bool inq[maxn];
    queue <int> Q;
    
    void SPFA(int s){
        dis[s] = w[s];
        inq[s] = 1;
        Q.push(s);
        
        while(!Q.empty()){
            int u = Q.front();
            Q.pop();
            inq[u] = 0;
            
            for(int i = 0; i < G[u].size(); i++){
                edge &e = G[u][i];
                if(dis[e.to] < dis[u] + e.co){
                    dis[e.to] = dis[u] + e.co;
                    if(!inq[e.to]){
                        Q.push(e.to);
                        inq[e.to] = 1;
                    }
                }
            }
        }
        
    }
    int main(){
        freopen("dag.in","r",stdin);
        freopen("dag.out","w",stdout);
        cin>>n>>m>>S;
        for(int i = 1; i <= n; i++)
            scanf("%d",&w[i]);
        for(int i = 1; i <= m; i++){
            int u, v;
            scanf("%d%d",&u,&v);
            G[u].push_back((edge){v,w[v]});
        }
        SPFA(S);
        for(int i = 1; i <= n; i++)
            ans = max(ans, dis[i]);
        cout<<ans<<endl;
    }

    美丽的有向图
    输入文件:beauty.in
    输出文件:beauty.out
    时间限制:1 second
    空间限制:128 MB
    题目描述
    定义一张有向图是美丽的,当且仅当任意选出两点:要么可以到,要么可以到.
    给定一张个点条边的有向图,判断是否是美的。如果是,输出I am beautiful! ,否则输出Go away Anna.
    输入格式
    题目包含多组数据。
    第一行一个数,表示数据组数。
    对于每一组数据:
    第一行n,m两个正整数,表示有n只猪猪和m个单向关系。
    接下来行,每一行两个数表示的单向关系。
    输出格式
    共行,每一行一个字符串,表示结果。
    样例
    样例输入

    2

    3 3
    1 2
    2 3
    3 1
    5 5
    1 2
    2 3
    2 4
    3 5
    4 5

    样例输出
    I am beautiful!
    Go away Anna.

    数据范围
    n <=10^5 , m <= n*(n-1)/2 ;

    题解:先tarjian缩点,拓扑时有出度为2的点就不行了;缩点有点问题,就贴一个标答

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200005;
    int dfn[maxn];//dfs顺序
    int low[maxn];
    int index1;//记录时间的标号
    bool state[maxn];//是否在栈里.
    stack<int>s;
    vector<int>G[maxn];
    vector<int>g[maxn];
    int cnt[maxn];
    int num[maxn], du[maxn];//num数组不一定要,各个强连通分量包含点的个数,数组编号1~cnt
    int scc,flag;//scc为强连通分量的个数
    int vis[maxn];
    void init()
    {
        scc = 0,flag=0;
        memset(du, 0, sizeof(du));
        memset(state, false, sizeof(state));
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(cnt, 0, sizeof(cnt));
        memset(vis, false, sizeof(vis));
        memset(num, 0, sizeof(num));
        while(!s.empty())
            s.pop();
        for(int i = 0; i < maxn; i++)
        {
            G[i].clear();
            g[i].clear();
        }
    }
    void tarjan(int u)//tarjan 处理强连通分量。
    {
        dfn[u] = low[u] = ++index1;
        s.push(u);
        state[u] = true;
        vis[u] = true;
        for(int i = 0; i < G[u].size(); i++)
        {
            int w = G[u][i];
            if(!vis[w])
            {
                tarjan(w);
                low[u] = min(low[w], low[u]);
            }
            else if(state[w])
            {
                low[u] = min(low[u], dfn[w]);
            }
        }
        if(low[u] == dfn[u])
        {
            scc++;
            for(;;)
            {
                int x = s.top();
                s.pop();
                cnt[x] = scc;//标记v点属于哪个强连通分量
                num[scc]++;//记录这个强连通分量有多少个点组成
                state[x] = false;
                if(x == u)break;
            }
        }
    }    queue<int>q;
    void topsort()
    {
        while (q.size()) q.pop();
        int sizz=0;
        for(int i=1;i<=scc;i++)
        {
            if(!du[i])
            {
                sizz++;
                q.push(i);
            }
        }
        if(sizz>=2) flag=1;//如果刚缩点后就有两个以上度为0的坑定不可以啊
        while(!q.empty()&&!flag)//拓扑找出度为2的点 
        {
            int u=q.front();
            q.pop();
            int siz=0;
            for(int i=0;i<g[u].size()&&!flag;i++)
            {
                int to=g[u][i];
                du[to]--;
                if(du[to]==0)
                {
                    siz++;
                    q.push(to);
                }
                
            }
            if(siz>=2) flag=1;
        }
    }
    int main()
    {
    //    freopen ( "beauty8.in", "r", stdin ) ;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&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=cnt[i];
                for(int j=0;j<G[i].size();j++)
                {
                    int v=cnt[G[i][j]];
                    if(u!=v)
                    {
                        g[u].push_back(v);
                        du[v]++;//入度
                    }
                }
            }
            topsort();
            puts ( flag ? "Go away Anna." : "I am beautiful!" ) ;
        }
        return 0;
    }
  • 相关阅读:
    理想解法
    IEEExtreme 2021
    day_1-python前期学习准备篇
    电梯模拟C++
    java线程_01——————————HelloWorld例子
    Unknown tag (c:forEach) 未知的标签
    自动生成Junit单元测试的插件 CodeProAnalytix
    Log4j笔记----01
    Springboot学习笔记_helloWorld篇
    支持开源,崇尚技术,追求真理,充实人生
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8409990.html
Copyright © 2011-2022 走看看