HDU 3873 Invade the Mars Dijkstra变种

47 篇文章 0 订阅
6 篇文章 0 订阅
Invade the Mars
Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 365768/165536 K (Java/Others)
Total Submission(s): 2136    Accepted Submission(s): 623


Problem Description
It'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.


Input
The 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.


Output
For each case,print a line with a number indicating the minimium time needed to enter the capital of the Mars.


Sample Input

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



Sample Output

5

Hint
The Map is like this:
We can follow these ways to achieve the fastest speed:
1->2->3,1->2->5,1->4->6.





Source
2011 Multi-University Training Contest 4 - Host by SDU


Recommend
lcy   |   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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值