所有负权回路的判断

http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1074

题目大意:给定路径的关系,问你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函数里用

posted @ 2018-03-13 20:12  Butterflier  阅读(665)  评论(0编辑  收藏  举报