1. 程式人生 > >XYZZY(spfa || dfs)

XYZZY(spfa || dfs)

題意:有N個房間,剛開始你位於1號房間,有100的能量值,你要到達N號房間,每兩個房間之間有單向門相連線,你到達某個房間可以加上該房間的能量值,如果你在未到達N號房間之前能量值耗盡,則死亡,否則勝利。

spfa思路:通過不斷地進行鬆弛操作,使得存在迴路的點對應的能量值不斷變大變大,或者是能量不斷變大的次數超過一個給定的值(這個值要很大很大,我設定的是10000),到達終點能量依然大於0為止。到不了終點或者到終點能量值耗盡,則死亡,否則勝利。

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3;
#define inf 0x3f3f3f3f
int n,m;
int d[maxn],vis[maxn],cnt[maxn];
vector<pair<int,int> >E[maxn];
void init()
{
    for(int i = 0; i < maxn; i++) vis[i] = 0, cnt[i] = 0;
    for(int i = 0; i < maxn; i++) d[i] = 0;
    for(int i = 0; i < maxn; i++) E[i].clear();
}
void spfa()
{
    d[1] = 100; vis[1] = 1;
    queue <int> Q;
        Q.push(1);
        while(!Q.empty())
        {
            int now = Q.front();
            Q.pop(); vis[now] = 0;
            for(int j = 0; j < E[now].size(); j++)
            {
                int v = E[now][j].first;
                if(d[v] < d[now] + E[now][j].second && cnt[v] < 10000)
                {
                    cnt[v]++;
                    d[v] = d[now] + E[now][j].second;
                    if(vis[v]) continue;
                    vis[v] = 1;
                    Q.push(v);
                }
            }
        }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n == -1) break;
        init();
        int a,b,x;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&x,&m);
            for(int j = 1; j <= m; j++)
            {
                scanf("%d",&b);
                E[i].push_back(make_pair(b,x));
            }
        }
        spfa();
        if(d[n] > 0) puts("winnable");
        else puts("hopeless");
    }
    return 0;
}

dfs思路:當發現有個和為正值的環存在時,直接求看該點能否直接到達終點。如果可以,直接返回true,即勝利。否則,繼續搜尋,當發現所有路徑都不能到達終點時,返回false。雖然能ac但不正確。

判斷正環的地方 d[u]+e[v]>d[v] 只是點u存在到點v的邊,從點u到點v會使點v的值增大,但是點v不一定存在路徑能回到點u,這個不一定是一個環。 一組很簡單的資料 7 0 2 2 4 -10 1 3 -10 1 6 -10 1 5 30 1 3 -200 1 7

0 0 應該輸出失敗但是輸出了成功 就是在點5到點3過程中,可以使點3的值增大,就判定點5和點3之間有正環,然後從點3找到了到終點7的通路,就判為成功,其實點5和點3之間沒有正環,整個圖都沒有環。

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3;
#define inf 0x3f3f3f3f
int n,m;
int d[maxn],vis[maxn], energy[maxn];
vector<int >E[maxn];
void init()
{
    for(int i = 0; i < maxn; i++) d[i] = 0, energy[i] = 0;
    for(int i = 0; i < maxn; i++) E[i].clear();
}
int dfs(int u)
{
    if(u == n) return 1;
    vis[u] = 1;
    for(int i  = 0; i < E[u].size(); i++)
    {
        int v = E[u][i];
        if(!vis[v])
        {
            if(dfs(v))
                return 1;
        }

    }
    return 0;
}
int DFS(int u, int e)
{
    if(u == n) return 1;
    d[u]  = energy[u] + e;
    for(int i  = 0; i < E[u].size(); i++)
    {
        int v = E[u][i];
        if(d[u] + energy[v] > 0)
        {
            if(!d[v])
            {
                if(DFS(v, d[u]))
                    return 1;
            }
            else if(d[v] < d[u] + energy[v])
            {
                memset(vis,0,sizeof(vis));
                if(dfs(v))
                    return 1;
            }
        }

    }
    return 0;
}
int main()
{
    int m,k;
    while(~scanf("%d",&n) && n != -1)
    {
         init();
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&energy[i],&m);
            for(int j = 1; j <= m; j++)
            {
                scanf("%d",&k);
                E[i].push_back(k);
            }
        }
        if(DFS(1,100)) puts("winnable");
        else puts("hopeless");
    }
    return 0;
}