zoukankan      html  css  js  c++  java
  • BZOJ1922: [Sdoi2010]大陆争霸

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1922

    带限制最短路。

    每个点真正的dis是max(dis[i],dis[v]),v是其保护点。

    可以把题目中的保护转化为每个点的贡献。

    每次扫一边连出的边做最短路把rd为0的点加入队列。

    再扫一遍自己的贡献,更新它们的d2,并让rd--,其中rd为0的点加入队列。

    (注意一下优先队列是大根堆。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 3005
    using namespace std;
    struct data{int x,y;
    };
    struct edge{int obj,pre,c;
    }e[70050];
    int a[maxn][maxn],d1[maxn],d2[maxn],head[maxn],vis[maxn],rd[maxn],l[maxn];
    int n,m,tot,mx;
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    void insert(int x,int y,int z){
        e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot; e[tot].c=z;
    }
    bool operator <(data a,data b){
        return a.y>b.y;
        //return a.x<b.x;
    }
    void dij(){
        priority_queue<data> q; q.push((data){1,0});
        clr(d1,127/3); d1[1]=0;
        while (!q.empty()){
            int u=q.top().x; q.pop();
            if (vis[u]) continue; vis[u]=1;
            int mx=max(d1[u],d2[u]);
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (mx+e[j].c<d1[v]) {
                    d1[v]=mx+e[j].c;
                    if (!rd[v]) q.push((data){v,max(d1[v],d2[v])});
                }
            }
            rep(i,1,l[u]){
                int v=a[u][i];
                rd[v]--; d2[v]=max(d2[v],mx);
                if (!rd[v]) q.push((data){v,max(d1[v],d2[v])});
            }
        }
    }
    int main(){
           n=read(); m=read();
           rep(i,1,m){
               int x=read(),y=read(),z=read();
               insert(x,y,z);
           }
           rep(i,1,n){
               rd[i]=read();
               rep(j,1,rd[i]){
                   int x=read();
                   a[x][++l[x]]=i;
               }
           }
           dij();
           printf("%d
    ",max(d1[n],d2[n]));
        return 0;
    }
  • 相关阅读:
    CodeForces 347B Fixed Points (水题)
    CodeForces 347A Difference Row (水题)
    CodeForces 346A Alice and Bob (数学最大公约数)
    CodeForces 474C Captain Marmot (数学,旋转,暴力)
    CodeForces 474B Worms (水题,二分)
    CodeForces 474A Keyboard (水题)
    压力测试学习(一)
    算法学习(一)五个常用算法概念了解
    C#语言规范
    异常System.Threading.Thread.AbortInternal
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5054946.html
Copyright © 2011-2022 走看看