题目大意:给定路径的关系,问你n个点的最短路,如果最短路的值比3小或无法到达,就输出?
又做到一个新类型的题目,但是不算太难,就是在spfa发现一个点的更新次数大于n侯进行的更新操作dfs
因为发现了一个负权回路点后,他直接间接能到的点都会是负权点(就是不存在最短路),而我们一开始用前向星存边也就十分方便了
多了的就是这个dfs
void dfs(int u)
{
cir[u] = 1;
for(int i = id[u];~i;i = edge[i].pre)
{
if(!cir[edge[i].to])
dfs(edge[i].to);
}
}
其余的就是裸spfa了,默写一遍吧
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 220;
int n;
struct node{
int to;
int cost;
int pre;
node(int t = 0,int c = 0,int pre = 0):to(t),cost(c),pre(pre){}
}edge[maxn * maxn];
int d[maxn];
int vis[maxn];
int tim[maxn];
int busy[maxn];
int cir[maxn];
int id[maxn];
int cnt;
queue<int>q;
void init()
{
cnt = 0;
memset(id,-1,sizeof(id));
memset(vis,0,sizeof(vis));
memset(tim,0,sizeof(tim));
memset(cir,0,sizeof(cir));
while(q.size())q.pop();
}
int getcost(int a,int b)
{
return (b - a) * (b - a) * (b - a);
}
void add(int from,int to,int cost)
{
edge[cnt] = node(to,cost,id[from]);
id[from] = cnt++;
}
void dfs(int u)
{
cir[u] = 1;
for(int i = id[u];~i;i = edge[i].pre)
{
if(!cir[edge[i].to])
dfs(edge[i].to);
}
}
void spfa(int s)
{
d[s] = 0;
vis[s] = 1;
tim[s]++;
q.push(s);
while(q.size())
{
int now = q.front();q.pop();vis[now] = 0;//cout<<now<<endl;
for(int i = id[now];~i;i = edge[i].pre)
{
//cout<<i<<endl;
int to = edge[i].to;
if(cir[to])continue;
if(d[to] > d[now] + edge[i].cost)
{
d[to] = d[now] + edge[i].cost;
if(!vis[to])
{
vis[to] = 1;
if(++tim[to] > n)
{
dfs(to);
}
else
{
q.push(to);
}
}
}
}
}
}
int main()
{
int t,m,a,b,q;
scanf("%d",&t);
int cas = 1;
while(t--)
{
init();
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
d[i] = inf;
scanf("%d",&busy[i]);
}
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
scanf("%d%d",&a,&b);
add(a,b,getcost(busy[a],busy[b]));
}
spfa(1);
printf("Case %d:\n",cas++);
scanf("%d",&q);
while(q--)
{
scanf("%d",&a);
if(cir[a] || d[a] < 3 || d[a] == inf)printf("?\n");
else printf("%d\n",d[a]);
}
}
return 0;
}
唯一坑了我的是写了init函数,却没有放到main函数里用