1. 程式人生 > >I - Xtreme NP-hard Problem?! Gym - 101806X 暴力+思維

I - Xtreme NP-hard Problem?! Gym - 101806X 暴力+思維

題目連結:http://codeforces.com/gym/101806/problem/X

題意:

        給你n個點m條邊,要求你求出走k步到點n的最短路。

 

做法:

       因為min(n,m,k)<=5,所以很明顯,當k>=n||k>m||k>5時,直接就是-1輸出,所以只要處理k<=5的情況,具體的情況我也很難形容,這裡貼一個部落格,覺得寫的挺好。https://blog.csdn.net/qq_41552508/article/details/82351819

 ,起碼我看懂了。也可以直接爆搜。。當時真沒敢這麼做。。


爆搜程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000005;
struct edge{
    int to,next;
    ll val;
}e[maxn<<1];
int n,m,k,x,y,head[maxn],now,vis[maxn];
ll w,ans;
void add(int u,int v,ll w){
    e[now].to=v,e[now].next=head[u];
    e[now].val=w,head[u]=now++;
}
void dfs(int now,int times,ll val){
    if(val>=ans) return ;
    if(now==n){
        if(times==k){
            ans=min(ans,val);
        }
        return ;
    }
    if(times>=k) return ;
    for(int i=head[now];~i;i=e[i].next){
        int t=e[i].to;
        if(vis[t]) continue;
        vis[t]=1;
        dfs(t,times+1,val+e[i].val);
        vis[t]=0;
    }
}
int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d%d%lld",&x,&y,&w);
        add(x,y,w); add(y,x,w);
    }
    if(k>=n||k>m||k>5) {
        printf("-1\n");
        return 0;
    }
    ans=8e17;
    vis[1]=1;
    dfs(1,0,0);
    if(ans==8e17) printf("-1\n");
    else printf("%lld\n",ans);

	return 0;
}

 

學習程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000005;
const int inf=1e9+7;
struct node{
    int to,next;
    ll val;
}e[maxn<<1];
struct edge{
    int u,v;
    ll w;
}ed[maxn];
int n,m,k,x,y,head[maxn],now,nume;
ll w,ans;
ll dist1[maxn][3],dist2[maxn][3];
int pre1[maxn][3],pre2[maxn][3];
void add(int u,int v,ll w){
    e[now].to=v,e[now].next=head[u];
    e[now].val=w,head[u]=now++;
}
int ck(int a,int b,int op1,int op2){
    if(dist1[a][op1]==inf||dist2[b][op2]==inf) return 0;
    int fa=pre1[a][op1],fb=pre2[b][op2];
    if(fa==1||fa==n||fb==1||fb==n||a==1||b==1||a==n||b==n) return 0;
    if(fa==fb||fa==b||fb==a||fa==-1||fb==-1||a==b) return 0;
    return 1;
}
void doit(int a,int b,int op1,int op2,ll w){
    if(ck(a,b,op1,op2))
        ans=min(ans,dist1[a][op1]+dist2[b][op2]+w);
}
void deal(){
    for(int i=1;i<=n;i++){
        for(int j=0;j<3;j++){
            pre1[i][j]=pre2[i][j]=-1;
            dist1[i][j]=dist2[i][j]=inf;
        }
    }
    for(int j=head[1];~j;j=e[j].next){
        int u=e[j].to; ll val1=e[j].val;
        if(u==n||u==1) continue;
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to; ll val2=e[i].val;
            if(v==1||v==n||v==u) continue;
            if(dist1[v][0]>val1+val2){
                dist1[v][2]=dist1[v][1],pre1[v][2]=pre1[v][1];
                dist1[v][1]=dist1[v][0],pre1[v][1]=pre1[v][0];
                dist1[v][0]=val1+val2,pre1[v][0]=u;
            }
            else if(dist1[v][1]>val1+val2){
                dist1[v][2]=dist1[v][1],pre1[v][2]=pre1[v][1];
                dist1[v][1]=val1+val2,pre1[v][1]=u;
            }
            else if(dist1[v][2]>val1+val2){
                dist1[v][2]=val1+val2,pre1[v][2]=u;
            }
        }
    }
    for(int j=head[n];~j;j=e[j].next){
        int u=e[j].to; ll val1=e[j].val;
        if(u==n||u==1) continue;
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to; ll val2=e[i].val;
            if(v==1||v==n||v==u) continue;
            if(dist2[v][0]>val1+val2){
                dist2[v][2]=dist2[v][1],pre2[v][2]=pre2[v][1];
                dist2[v][1]=dist2[v][0],pre2[v][1]=pre2[v][0];
                dist2[v][0]=val1+val2,pre2[v][0]=u;
            }
            else if(dist2[v][1]>val1+val2){
                dist2[v][2]=dist2[v][1],pre2[v][2]=pre2[v][1];
                dist2[v][1]=val1+val2,pre2[v][1]=u;
            }
            else if(dist2[v][2]>val1+val2){
                dist2[v][2]=val1+val2,pre2[v][2]=u;
            }
        }
    }
    for(int i=1;i<=nume;i++){
        int u=ed[i].u,v=ed[i].v; ll w=ed[i].w;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                doit(u,v,i,j,w);
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                doit(v,u,i,j,w);
    }
}
int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d%d%lld",&x,&y,&w);
        add(x,y,w); add(y,x,w);
        ed[++nume].u=x,ed[nume].v=y,ed[nume].w=w;
    }
    if(k>=n||k>m||k>5) {
        printf("-1\n");
        return 0;
    }
    ans=8e17;
    while(k<5){
        add(n,n+1,0);add(n+1,n,0);
        ed[++nume].u=n,ed[nume].v=n+1,ed[nume].w=0;
        n++,k++;
    }
    deal();
    if(ans==8e17) printf("-1\n");
    else printf("%lld\n",ans);
//
	return 0;
}