1. 程式人生 > >BZOJ3436: 小K的農場(差分約束裸題&DFS優化判環)

BZOJ3436: 小K的農場(差分約束裸題&DFS優化判環)

3436: 小K的農場

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2111  Solved: 986
[Submit][Status][Discuss]

Description

背景 小K是個特麼喜歡玩MC的孩紙。。。 描述 小K在MC裡面建立很多很多的農場,總共n個,以至於他自己都忘記了每個農場中種植作物的具體數量了,他只記得 一些含糊的資訊(共m個),以下列三種形式描述:農場a比農場b至少多種植了c個單位的作物,農場a比農場b至多 多種植了c個單位的作物,農場a與農場b種植的作物數一樣多。但是,由於小K的記憶有些偏差,所以他想要知道存 不存在一種情況,使得農場的種植作物數量與他記憶中的所有資訊吻合。

Input

第一行包括兩個整數n和m,分別表示農場數目和小K記憶中的資訊的數目接下來m行:如果每行的第一個數是1,接 下來有三個整數a,b,c,表示農場a比農場b至少多種植了c個單位的作物如果每行第一個數是2,接下來有三個整數a ,b,c,表示農場a比農場b至多多種植了c個單位的作物如果每行第一個數是3,接下來有兩個整數a,b,表示農場a 種植的數量與b一樣。1<=n,m,a,b,c<=10000

Output

如果存在某種情況與小K的記憶吻合,輸出”Yes”,否則輸出”No”

Sample Input

3 3
3 1 2
1 1 3 1
2 2 3 2

Sample Output

Yes
樣例解釋
三個農場種植的數量可以為(2,2,1)

HINT

Source

Kpmcup#0 By Greens

 

用dis表示不等式,然後跑最短路或者最長路即可。 9520ms

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
int Laxt[maxn],Next[maxn],To[maxn],Len[maxn];
int cnt,vis[maxn],num[maxn],dis[maxn],N;
void add(int u,int v,int w){ Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w; } bool SPFA() { queue<int>q; memset(dis,-1,sizeof(dis)); dis[0]=0; q.push(0); vis[10]=1; num[0]++; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=Laxt[u];i;i=Next[i]){ int v=To[i]; if(dis[v]<dis[u]+Len[i]){ dis[v]=dis[u]+Len[i]; if((++num[v])==N) return false; if(!vis[v]) vis[v]=1,q.push(v); } } } return true; } int main() { int M,opt,a,b,c; scanf("%d%d",&N,&M); rep(i,1,N) add(0,i,0); rep(i,1,M){ scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&a,&b,&c); add(b,a,c); } else if(opt==2) { scanf("%d%d%d",&a,&b,&c); add(a,b,-c); } else { scanf("%d%d",&a,&b); add(a,b,0); add(b,a,0); } } if(SPFA()) puts("Yes"); else puts("No"); return 0; }

然後優化了一下,把次數改為前者+1,而不是自加1。4452ms。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=20010;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1],Len[maxn<<1];
int cnt,vis[maxn],num[maxn],dis[maxn],N;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
bool SPFA()
{
    queue<int>q;
    memset(dis,-1,sizeof(dis));
    dis[0]=0; q.push(0); vis[0]=1; num[0]++;
    while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=0;
        for(int i=Laxt[u];i;i=Next[i]){ int v=To[i];
            if(dis[v]<dis[u]+Len[i]){
                dis[v]=dis[u]+Len[i];
                num[v]=num[u]+1;
                if(num[v]==N) return false;
                if(!vis[v]) vis[v]=1,q.push(v);
            }
        }
    }
    return true;
}
int main()
{
    int M,opt,a,b,c;
    scanf("%d%d",&N,&M);
    rep(i,1,N) add(0,i,0);
    rep(i,1,M){
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d%d%d",&a,&b,&c);
            add(b,a,c);
        }
        else if(opt==2) {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,-c);
        }
        else {
            scanf("%d%d",&a,&b);
            add(a,b,0); add(b,a,0);
        }
    }
    if(SPFA()) puts("Yes");
    else puts("No");
    return 0;
}

把queue改為stack,然後就124ms了,估計不是因為queue比stack快,而是資料使然。

(據說是改為stck變為深搜DFS了!)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=20010;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1],Len[maxn<<1];
int cnt,vis[maxn],num[maxn],dis[maxn],N;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
bool SPFA()
{
    stack<int>q;
    memset(dis,-1,sizeof(dis));
    dis[0]=0; q.push(0); vis[0]=1; num[0]++;
    while(!q.empty()){
        int u=q.top(); q.pop(); vis[u]=0;
        for(int i=Laxt[u];i;i=Next[i]){ int v=To[i];
            if(dis[v]<dis[u]+Len[i]){
                dis[v]=dis[u]+Len[i];
                num[v]=num[u]+1;
                if(num[v]==N) return false;
                if(!vis[v]) vis[v]=1,q.push(v);
            }
        }
    }
    return true;
}
int main()
{
    int M,opt,a,b,c;
    scanf("%d%d",&N,&M);
    rep(i,1,N) add(0,i,0);
    rep(i,1,M){
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d%d%d",&a,&b,&c);
            add(b,a,c);
        }
        else if(opt==2) {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,-c);
        }
        else {
            scanf("%d%d",&a,&b);
            add(a,b,0); add(b,a,0);
        }
    }
    if(SPFA()) puts("Yes");
    else puts("No");
    return 0;
}