zoukankan      html  css  js  c++  java
  • 《8.12solution》

    1001 : 点双连通分量:

    tarjan模板题:需要注意的是,点双连通分量是极大子图,也就是说他如果是很多个环拼成一个环,那么这个分量还是一个,就是最大的那个。

    我们从环顶退栈即可,类似割点的位置。

    / Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 2e5 + 5;
    const int M = 2e3 + 5;
    const LL Mod = 100000007;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,m,dfn[N],low[N],tim = 0,cnt = 0;
    vector<int> G[N];
    stack<int> S;
    void tarjan(int u,int fa) {
        dfn[u] = low[u] = ++tim;
        S.push(u);
        for(auto v : G[u]) {
            if(!dfn[v]) {
                tarjan(v,u);
                low[u] = min(low[u],low[v]);
                if(low[v] >= dfn[u]) {
                    ++cnt;
                    while(S.top() != v) S.pop();
                }
            }
            else if(v != fa) low[u] = min(low[u],dfn[v]);
        }
    }
    int main() {
        scanf("%d %d",&n,&m);
        while(m--) {
            int x,y;scanf("%d %d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        tarjan(1,0);
        printf("%d
    ",cnt);
    
       // system("pause");
        return 0;
    }
    /*
    4 5
    1 2
    1 3
    1 4
    2 3
    3 4
    
    */
    View Code

    1002 : Play on Words:

    这里一开始忘记判断连通图了所以一直wa。

    首先我们可以把每个单词看成连u -> v的一条有向边。

    那么就是题目就是问是否存在一条欧拉通路。

    条件就是:所有点的入度 = 出度,或者只存在一个点满足入度 - 出度 = 1 and 出度 - 入度 = 1

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 2e5 + 5;
    const int M = 2e3 + 5;
    const LL Mod = 100000007;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int fa[30],in[30],out[30];
    bool vis[30];
    int Find(int x) {
        return x == fa[x] ? x : fa[x] = Find(fa[x]);
    }
    int main() {
        int ca;scanf("%d",&ca);
        while(ca--) {
            int n;scanf("%d",&n);
            for(int i = 0;i <= 25;++i) fa[i] = i,in[i] = out[i] = 0;
            memset(vis,0,sizeof(vis));
            for(int i = 1;i <= n;++i) {
                string s;cin >> s;
                int x = s[0] - 'a',y = s[s.size() - 1] - 'a';
                vis[x] = vis[y] = 1;
                if(x != y) {
                    in[x]++,out[y]++;
                    int xx = Find(x),yy = Find(y);
                    fa[xx] = yy;
                }
            }
            int cnt = 0,tag1 = 0,tag2 = 0;
            for(int i = 0;i <= 25;++i) {
                if(vis[i] == 0) continue;
                if(fa[i] == i) cnt++;
                if(in[i] != out[i]) {
                    if(in[i] - out[i] == 1) tag1++;
                    else if(out[i] - in[i] == 1) tag2++;
                    else cnt = 2;
                }
            }
            if(cnt > 1 || tag1 > 1 || tag2 > 1) printf("The door cannot be opened.
    ");
            else printf("Ordering is possible.
    ");
        }
    
      //  system("pause");
        return 0;
    }
    View Code

    1003 : Currency Exchange:

    一开始的思路有点问题,直接认为第二次走到这个点比上一次更优就是在正权值环里了,但是有可能第二次是从另一条路过来的,值比上一次大。

    所有还是慢慢松弛到比原来大比较好,优先队列会掉到无限环里,所以spfa松弛就可以了。

    // Author: levil
    #include<iostream>
    #include<stdio.h>
    #include<queue>
    #include<algorithm>
    #include<math.h>
    #include<stack>
    #include<map>
    #include<limits.h>
    #include<vector>
    #include<string.h>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef pair<double,int> pii;
    const int N = 105;
    const int M = 1e3 + 5;
    const LL Mod = 100000007;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,m,s,tot = 0,head[N];
    bool vis[N];
    double dp[N],V;
    struct Node{int to,next;double r,c;}e[M << 1];
    void init() {
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        tot = 0;
    }
    void add(int u,int v,double r,double c) {
        e[++tot].to = v,e[tot].r = r,e[tot].c = c,e[tot].next = head[u],head[u] = tot;
    }
    bool solve() {
        for(int i = 1;i <= n;++i) dp[i] = 0;
        queue<int> Q;
        dp[s] = V;
        vis[s] = 1;
        Q.push(s);
        while(!Q.empty()) {
            int u = Q.front();
            vis[u] = 0;
            Q.pop();
            for(int i = head[u];i;i = e[i].next) {
                int v = e[i].to;
                double ma = (dp[u] - e[i].c) * e[i].r;
                //printf("v is %d ma is %.2f
    ",v,ma);
                if(dp[v] < ma) {
                    dp[v] = ma;
                    if(dp[s] > V) return true;
                    if(vis[v] == 0) {
                        Q.push(v);
                        vis[v] = 1;
                    }
                }
            }
        }
        return false;
    }
    int main() {
        while(~scanf("%d %d %d %lf",&n,&m,&s,&V)) {
            init();
            while(m--) {
                int u,v;
                double r1,c1,r2,c2;
                scanf("%d %d %lf %lf %lf %lf",&u,&v,&r1,&c1,&r2,&c2);
                add(u,v,r1,c1);
                add(v,u,r2,c2);
            }
            printf("%s
    ",solve() ? "YES" : "NO");
        }
    
        //system("pause");
        return 0;
    }
    /*
    4 4 1 20.0
    1 2 1.00 1.00 1.00 1.00
    2 3 1.10 1.00 1.00 1.00
    3 4 1.10 1.00 1.00 1.00
    4 2 1.10 1.00 1.00 1.00
    */
    View Code

    1004 : 点的距离:

    LCA裸题没什么好说的。这里询问的数量不够明显,所以写的st表比普通还慢。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 1e5 + 5;
    const int M = 2e3 + 5;
    const LL Mod = 100000007;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,st[N << 1][30],dep[N],dfn[N],lg[N << 1],tim = 0,tot = 0;
    vector<int> G[N];
    void dfs(int u,int fa) {
        dfn[u] = ++tot;
        dep[u] = dep[fa] + 1;
        st[tot][0] = u;
        for(auto v : G[u]) {
            if(v == fa) continue;
            dfs(v,u);
            st[++tot][0] = u;
        }
    }
    void init() {
        lg[1] = 0;
        for(int i = 2;i <= tot;++i) lg[i] = lg[i >> 1] + 1;
        for(int j = 1;(1 << j) <= tot;++j) {
            for(int i = 1;i + (1 << j) - 1 <= tot;++i) {
                if(dep[st[i][j - 1]] <= dep[st[i + (1 << j - 1)][j - 1]]) st[i][j] = st[i][j - 1];
                else st[i][j] = st[i + (1 << j - 1)][j - 1];
            }
        }
    }
    int LCA(int x,int y) {
        x = dfn[x],y = dfn[y];
        if(x > y) swap(x,y);
        int k = lg[y - x + 1];
        if(dep[st[x][k]] < dep[st[y - (1 << k) + 1][k]]) return st[x][k];
        else return st[y - (1 << k) + 1][k];
    }
    int query(int x,int y) {
        return dep[x] + dep[y] - 2 * dep[LCA(x,y)];
    }
    int main() {
        scanf("%d",&n);
        for(int i = 1;i < n;++i) {
            int x,y;scanf("%d %d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1,0);
        init();
        int q;scanf("%d",&q);
        while(q--) {
            int x,y;scanf("%d %d",&x,&y);
            printf("%d
    ",query(x,y));
        }
    
       // system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    计算机考研复试真题 数字求和
    计算机考研复试真题 简单计算器
    计算机考研复试真题 N阶楼梯上楼问题
    P1082 [NOIP2012 提高组] 同余方程
    进制转换
    浮点数加法
    N的阶乘
    1055 The World's Richest (25 分)
    1028 List Sorting (25 分)
    1062 Talent and Virtue (25 分)
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/15133814.html
Copyright © 2011-2022 走看看