HDU 3873 Invade the Mars Dijkstra变种

来源:互联网 发布:邦家博士骗局揭秘 知乎 编辑:程序博客网 时间:2024/04/28 15:42
Invade the MarsTime Limit: 5000/2000 MS (Java/Others)    Memory Limit: 365768/165536 K (Java/Others)Total Submission(s): 2136    Accepted Submission(s): 623Problem DescriptionIt's now the year 21XX,when the earth will explode soon.The evil U.S. decided to invade the Mars to save their lives.But the childlike Marsmen never keeps any army,because war never take place on the Mars.So it's very convenient for the U.S. to act the action.Luckily,the Marsmen find out the evil plan before the invadation,so they formed a defense system.The system provides enchantment for some citys,and the enchantment generator for city A maybe set in city B,and to make things worse,both city B and C and more will provide echantment for city A.The satelite of U.S. has got the map of the Mars.And they knows that when they enter a city,they can destory all echantment generator in this city at once,and they can enter a city only if they has destoryed all enchantment generator for this city,but troops can stay at the outside of the city and can enter it at the moment its echantment is destoryed.Of course the U.S. army will face no resistance because the Mars keep no army,so troops can invade in many way at the same time.Now the U.S. will invade the Mars,give you the map,your task is to calculate the minimium time to enter the capital of the Mars.InputThe first line contains an integer T,which is the number of test cases.For each testcase:The first line contains two integers N and M,1<=N<=3000,1<=M<=70000,the cities is numbered from 1 to N and the U.S. landed on city 1 while the capital of the Mars is city N.The next M lines describes M paths on the Mars.Each line contains three integers ai,bi and wi,indicates there is a unidirectional path form ai to bi lasts wi minutes(1<=wi<=10^8).The next N lines describes N citys,the 1+M+i line starts with a integer li,followed with li integers, which is the number of cities has a echantment generator protects city i.It's guaranteed that the city N will be always reachable.OutputFor each case,print a line with a number indicating the minimium time needed to enter the capital of the Mars.Sample Input16 61 2 11 4 32 3 12 5 24 6 25 3 20001 302 3 5Sample Output5HintThe Map is like this:We can follow these ways to achieve the fastest speed:1->2->3,1->2->5,1->4->6.Source2011 Multi-University Training Contest 4 - Host by SDURecommendlcy   |   We have carefully selected several similar problems for you:  3870 3869 3871 3878 3872 

令pNum[i]=保护城市i的城市个数
pTime[i]=保护i的城市被攻破的最晚时间
toTime[i]=到达i城外的最短时间
dist[i]=攻破i的最短时间
当pNum=0时:dist[i]=max(pTime[i],toTime[i])

在Dijkstra中 不断更新toTime[v]
if(pNum==0)更新dist[v]

当u出队列时 显然dist[u]达到了最小值 此时更新u保护的v的pTime[v]
if(pNum[v]==0)将v加入队列

PS:当有k个点对u进行过松弛,u会入队k次,对u保护的v
pNum[v]显然只需要-1 所以需要标记u是否已经出过队列..(此处WA N次)

#include<iostream>#include<stdlib.h>#include<stdio.h>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<time.h>#include<math.h>#include<list>#include<cstring>#include<fstream>//#include<memory.h>using namespace std;#define ll long long#define ull unsigned long long#define pii pair<int,int>#define INF 1000000007#define pll pair<ll,ll>#define pid pair<int,double>const ll inf=1e16;const int N=3000+5;const int M=70000+5;struct Edge{//到达的城    int to,cost,next;}edge[M];int head[N];struct Protect{//保护的城    int v,next;}edgeP[N*N];int headP[N];inline void addEdge(int k,int u,int v,int c){    edge[k].to=v;    edge[k].cost=c;    edge[k].next=head[u];    head[u]=k;}inline void addEdgeP(int k,int u,int v){    edgeP[k].v=v;    edgeP[k].next=headP[u];    headP[u]=k;}ll dist[N];//进入i的最短时间ll toTime[N];//到i城外的最短时间ll pTime[N];//保护i的城被攻破的最长时间ll vis[N];//标记是i否被pop过了 当有k个点对i进行过松弛操作,i会进入队列k次 显然 当i城被pop出队列 dist[i]已经是到达i的最短时间 update ptime[被i保护的城] 而--pNum[v]可能被执行k次int pNum[N];//pNum[i]=还在保护i城的城市数void Dijkstra(int n){    fill(dist,dist+n+1,inf);    fill(toTime,toTime+n+1,inf);    fill(pTime,pTime+n+1,0);    fill(vis,vis+n+1, false);    priority_queue<pii,vector<pii>,greater<pii> >que;    dist[1]=0;    que.push({dist[1],1});    while(!que.empty()){        int u=que.top().second;        que.pop();        if(vis[u])            continue;        vis[u]=true;        for(int i=headP[u];i!=-1;i=edgeP[i].next){            int v=edgeP[i].v;            --pNum[v];            pTime[v]=max(pTime[v],dist[u]);            if(pNum[v]==0){                dist[v]=max(pTime[v],toTime[v]);                que.push({dist[v],v});            }        }        for(int i=head[u];i!=-1;i=edge[i].next){            int v=edge[i].to,c=edge[i].cost;            toTime[v]=min(toTime[v],dist[u]+c);            if(pNum[v]>0)                continue;            ll tmpTime=dist[v];            dist[v]=max(pTime[v],toTime[v]);            if(dist[v]<tmpTime){                que.push({dist[v],v});            }        }    }}int main(){    freopen("/home/lu/文档/r.txt","r",stdin);    //freopen("/home/lu/文档/w.txt","w",stdout);    int n,m,T;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        fill(head,head+n+1,-1);        fill(headP,headP+n+1,-1);        fill(pNum,pNum+n+1,0);        for(int i=0,u,v,c;i<m;++i){            scanf("%d%d%d",&u,&v,&c);            addEdge(i,u,v,c);        }        for(int i=1,li,u,counter=0;i<=n;++i){            scanf("%d",&li);            pNum[i]=li;            while(li--){                scanf("%d",&u);                addEdgeP(counter++,u,i);            }        }        Dijkstra(n);        printf("%lld\n",dist[n]);    }    return 0;}
0 0