您的位置:首页 > 其它

【HDU3873 Invade the Mars】有保护节点的最短路(优先队列+spfa)

2013-05-03 14:04 246 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3873

题目大意:美国佬打算入侵火星,火星上有n个城市,有些城市可能受其他城市保护,如果i城市受j城市保护,那么你必须先攻占j城市才能再攻占i城市,问你攻占城市n的最短时间是多少。

解题思路:开一个优先队列,每次将图中不受保护并的节点加入队列(注意不受保护的节点可能重复入队,所以要做个标记,只处理优先队列中第一个出来的重复节点),spfa()单源最短路进行操作,num[u]表示保护节点u的城市有多少个,当num[u]为0的时候可以把u加入队列。处理受保护的节点v时,disv=max(disu,dis[v]),disu表示达到保护u的最后一个节点的时间,dis[v]表示spfa到达v的最短时间,两者取最大值。

View Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=3333;
const long long oo=1000000007ll;
typedef long long lld;
int visit[maxn], num[maxn];
lld  dis[maxn];
int n;

struct node
{
int x;
lld dis;
friend bool operator<(const node &A, const node &B)
{
return A.dis>B.dis;
}
};

struct Node
{
int v, val;
Node() {}
Node(int v_, int val_)
{
v=v_, val=val_;
}
};
vector<Node>vt[maxn];
vector<int>ct[maxn];

void spfa()
{
for(int i=1; i<=n; i++) dis[i]=oo, visit[i]=0;
priority_queue<node>q;
node s;
s.x=1, s.dis=0;
dis[s.x]=0;
q.push(s);
while(!q.empty())
{
int u=q.top().x;
lld du=q.top().dis;
q.pop();
if(visit[u]) continue;  ///访问过的节点就不必在处理了
visit[u]=1;
if(u==n)
{
cout << du <<endl;
return ;
}
for(int i=0; i<vt[u].size(); i++)
{
s.x=vt[u][i].v, s.dis=du+vt[u][i].val;
if(s.dis<dis[s.x])
{
dis[s.x]=s.dis;
if(!num[s.x])   q.push(s);
}
}
for(int i=0; i<ct[u].size(); i++)
{
s.x=ct[u][i];
if(visit[s.x]) continue;
num[s.x]--;
if(!num[s.x])
{
s.dis=max(du,dis[s.x]);
q.push(s);
}
}
}
}

int main()
{
int m, T;
cin >> T;
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) vt[i].clear(), ct[i].clear(), num[i]=0;
for(int i=0; i<m; i++)
{
int u, v, val;
scanf("%d%d%d",&u,&v,&val);
vt[u].push_back(Node(v,val));
}
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&num[i]);
for(int j=1; j<=num[i]; j++)
{
scanf("%d",&x);
ct[x].push_back(i);
}
}
spfa();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: