zoukankan      html  css  js  c++  java
  • Codeforces Bubble Cup 8

    B. Bribes

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://codeforces.com/contest/575/problem/B

    Description

    Ruritania is a country with a very badly maintained road network, which is not exactly good news for lorry drivers that constantly have to do deliveries. In fact, when roads are maintained, they become one-way. It turns out that it is sometimes impossible to get from one town to another in a legal way – however, we know that all towns are reachable, though illegally!

    Fortunately for us, the police tend to be very corrupt and they will allow a lorry driver to break the rules and drive in the wrong direction provided they receive ‘a small gift’. There is one patrol car for every road and they will request 1000 Ruritanian dinars when a driver drives in the wrong direction. However, being greedy, every time a patrol car notices the same driver breaking the rule, they will chargedouble the amount of money they requested the previous time on that particular road.

    Borna is a lorry driver that managed to figure out this bribing pattern. As part of his job, he has to make K stops in some towns all over Ruritania and he has to make these stops in a certain order. There are N towns (enumerated from 1 to N) in Ruritania and Borna’s initial location is the capital city i.e. town 1. He happens to know which ones out of the N - 1 roads in Ruritania are currently unidirectional, but he is unable to compute the least amount of money he needs to prepare for bribing the police. Help Borna by providing him with an answer and you will be richly rewarded.

    Input

    The first line contains N, the number of towns in Ruritania. The following N - 1 lines contain information regarding individual roads between towns. A road is represented by a tuple of integers (a,b,x), which are separated with a single whitespace character. The numbers a and b represent the cities connected by this particular road, and x is either 0 or 1: 0 means that the road is bidirectional, 1 means that only the a → b direction is legal. The next line contains K, the number of stops Borna has to make. The final line of input contains K positive integers s1, …, sK: the towns Borna has to visit.

    • 1 ≤ N ≤ 105
    • 1 ≤ K ≤ 106
    • 1 ≤ a, b ≤ N for all roads
    •  for all roads
    • 1 ≤ si ≤ N for all 1 ≤ i ≤ K

    Output

    The output should contain a single number: the least amount of thousands of Ruritanian dinars Borna should allocate for bribes, modulo109 + 7.

    Sample Input

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

    Sample Output

    4

    HINT

     

    题意

    给你一棵树,有些边是无向边,有些边是有向边

    每次你反方向走有向边的时候,就会使得这条边的边权乘以2

    然后最后问你这个树的所有边权和是多少

    题解:

    建两棵树咯

    比如从a->b,lca(a,b)=c,那就记录标记,第一棵树 a++,c--;第二棵树b++,c--;

    最后按照深度排序,然后跑BFS统计一下每个边的和就好了……

    大概就是酱紫,记录一下标记就吼了

    代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int MAXN=1000005;
    const int DEG=20;
    const int MOD=1000000007;
    struct Edge
    {
        int to,next,type;
    }edge[MAXN*2];
    int head[MAXN],tot;
    void addedge(int u,int v,int type)
    {
        edge[tot].to=v;
        edge[tot].next=head[u];
        edge[tot].type=type;
        head[u]=tot++;
    }
    void init()
    {
        tot=0;
        memset(head,-1,sizeof(head));
    }
    int fa[MAXN][DEG];
    int deg[MAXN],up[MAXN];
    int cnt[2][MAXN];
    void BFS(int root)
    {
        queue<int>q;
        deg[root]=0;
        fa[root][0]=root;
        up[root]=0;
        q.push(root);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=1;i<DEG;i++)
                fa[u][i]=fa[fa[u][i-1]][i-1];
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(v==fa[u][0])continue;
                deg[v]=deg[u]+1;
                fa[v][0]=u;
                up[v]=-edge[i].type;
                q.push(v);
            }
        }
    }
    void DFS(int u)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==fa[u][0])continue;
            DFS(v);
            for(int j=0;j<2;j++)
                cnt[j][u]+=cnt[j][v];
        }
    }
    int LCA(int u,int v)
    {
        if(deg[u]>deg[v])swap(u,v);
        int hu=deg[u],hv=deg[v];
        int tu=u,tv=v;
        for(int det=hv-hu,i=0;det;det>>=1,i++)
            if(det&1)
                tv=fa[tv][i];
        if(tu==tv)return tu;
        for(int i=DEG-1;i>=0;i--)
        {
            if(fa[tu][i]==fa[tv][i])continue;
            tu=fa[tu][i];
            tv=fa[tv][i];
        }
        return fa[tu][0];
    }
    int fp(int a,int k)
    {
        int res=1;
        while(k)
        {
            if(k&1)res=1LL*res*a%MOD;
            a=1LL*a*a%MOD;
            k>>=1;
        }
        return res;
    }
    int main()
    {
        init();
        int n;
        scanf("%d",&n);
        int a,b,x;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&x);
            if(x==0)
            {
                addedge(a,b,0);
                addedge(b,a,0);
            }
            else
            {
                addedge(a,b,1);
                addedge(b,a,-1);
            }
        }
        int root=1;
        BFS(root);
        int k,la=1,now;
        scanf("%d",&k);
        while(k--)
        {
            scanf("%d",&now);
            if(la==now)continue;
            int tp=LCA(la,now);
            cnt[0][la]++;
            cnt[0][tp]--;
            cnt[1][now]++;
            cnt[1][tp]--;
            la=now;
        }
        DFS(root);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(!up[i])continue;
            if(up[i]==-1)
                ans=(ans+fp(2,cnt[0][i])-1)%MOD;
            else
                ans=(ans+fp(2,cnt[1][i])-1)%MOD;
        }
        ans=(ans+MOD)%MOD;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    复旦大学2016--2017学年第二学期(16级)高等代数II期末考试第八大题解答
    复旦大学2016--2017学年第二学期高等代数II期末考试情况分析
    16 级高代 II 思考题十的多种证明
    16 级高代 II 思考题九的七种解法
    Jordan 块的几何
    实对称阵可对角化的几种证明及其推广
    复旦大学高等代数在线课程2017--2018学年记录
    复旦高等代数II(16级)每周一题
    复旦大学2016--2017学年第一学期(16级)高等代数I期末考试第六大题解答
    复旦大学2016--2017学年第一学期(16级)高等代数I期末考试第七大题解答
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4787602.html
Copyright © 2011-2022 走看看