【题解】 P5022旅行

【题解】P5022 旅行

当给定你一颗树的时候,这题就是一道送分题,凉心啊!

但是给定你一颗基环树呢?

暴力断环直接跑。

但是数据范围\(n\le 1000\)

乱做就完事了。

考场上这样想的,对于\(m=n​\)的情况,得出来的最佳方案一定没有经过一条树边。那么我们直接枚举那条边不能走,直接\(O(n^2)​\)过就好了。

不过这样的算法有一个\(bug\),是因为\(dfs\)在节点上需要枚举哪个点最小,很可能被卡到\(O(n^3)\),但是\(ccf\)今年换配置了,而且不可能每个点都要枚举\(O(n)\),因为是一棵树,只有一种到达方式。那么就取得了\(96\)分的好成绩。

要是\(D1T2\)没有挂题我就1=了!!

悲伤QAQ

当然,针对上述那种被卡,有很简单的办法解决,我们用的是链式前向星,直接加边的时候把小的后面加进去就好了。

考场代码(\(96\))

#include<bits/stdc++.h>
using namespace std;
inline int qr(){
    char c=getchar();
    int x=0,q=1;
    while(c<48||c>57)
    q=c==45?-1:q,c=getchar();
    while(c>=48&&c<=57)
    x=x*10+c-48,c=getchar();
    return q==-1?-x:x;
}
#define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++)
#define DRP(t,a,b) for(int t=(a),edd=(b);t>=edd;t--)
#define ERP(t,a) for(int t=head[a];t;t=e[t].nx)
#define more(a,b) (a)=(a)>(b)?(a):(b)
#define few(a,b) (a)=(a)<(b)?(a):(b)
typedef long long ll;
const int maxn=5005;
struct E{
    int to,num,nx;
}e[maxn<<1];
int head[maxn];
bool can[maxn];
int cnt;
inline void add(int fr,int to,int num,bool f){
    e[++cnt]=(E){to,num,head[fr]};
    head[fr]=cnt;
    if(f)
    add(to,fr,num,0);
}
int n,m;
int ans[maxn];
int dfn[maxn];
bool usd[maxn];
int top;
bool better;
const int inf=0x3f3f3f3f;
void dfs(int now,int last,int pos){
    //cout<<now<<' '<<last<<' '<<pos<<endl;
    dfn[++top]=now;
    int sav=inf,pin=0;
    bool flg=1;
    while(flg){
    flg=0;
    sav=inf;
    pin=0;
    ERP(t,now)
        if((e[t].to!=last)&&(!usd[e[t].to])&&(e[t].to<sav)&&(!can[e[t].num]))
        sav=e[t].to,pin=t,flg=1;
    //cout<<"now="<<now<<" sav="<<sav<<" flg="<<flg<<endl;
    if(flg)
        usd[e[pin].to]=1,dfs(e[pin].to,now,pos+1);
    }
}



int t1,t2,t3;
inline void init(){
    n=qr();
    m=qr();
    memset(ans,0x3f,sizeof ans);
    RP(t,1,m){
    t1=qr();
    t2=qr();
    add(t1,t2,t,1);
    }
    if(m==n-1){
    dfs(1,0,1);
    RP(t,1,n)
        cout<<dfn[t]<<' ';
    cout<<endl;
    return;
    }
    else{
    RP(t,1,m){
        top=0;
        better=0;
        memset(usd,0,sizeof usd);
        can[t]=1;
        dfs(1,0,1);
        can[t]=0;
        if(top==n){
        RP(t,1,n){
            if(dfn[t]!=ans[t]){
            if(dfn[t]<ans[t])
                better=1;
            break;
            }
        }
        }
        if(better&&top==n)
        RP(t,1,n)
            ans[t]=dfn[t];
    }
    }
    RP(t,1,n)
    cout<<ans[t]<<' ';
    cout<<endl;
    return;
    
}




int main(){
//    freopen("travel.in","r",stdin);
//    freopen("travel.out","w",stdout);
    init();
    return 0;
}

\(AC\)代码

#include<bits/stdc++.h>
using namespace std;
inline int qr() {
    char c=getchar();
    int x=0,q=1;
    while(c<48||c>57)
        q=c==45?-1:q,c=getchar();
    while(c>=48&&c<=57)
        x=x*10+c-48,c=getchar();
    return q==-1?-x:x;
}
#define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++)
#define DRP(t,a,b) for(int t=(a),edd=(b);t>=edd;t--)
#define ERP(t,a) for(int t=head[a];t;t=e[t].nx)
#define more(a,b) (a)=(a)>(b)?(a):(b)
#define few(a,b) (a)=(a)<(b)?(a):(b)
typedef long long ll;
const int maxn=5005;
struct E {
    int to,num,nx;
} e[maxn<<1];
struct sav {
    int fr,to,num;
} data[maxn<<1];
int head[maxn];
bool can[maxn];
int cnt;
inline bool cmp(sav a,sav b) {
    return a.to>b.to;
}
inline void add(int fr,int to,int num) {
    e[++cnt]=(E) {
        to,num,head[fr]
    };
    head[fr]=cnt;
}
int n,m;
int ans[maxn];
int dfn[maxn];
bool usd[maxn];
int top;
bool better;
const int inf=0x3f3f3f3f;
void dfs(int now,int last,int pos) {
    dfn[++top]=now;
    ERP(t,now) {
        if((e[t].to!=last)&&(!usd[e[t].to])&&(!can[e[t].num]))
            usd[e[t].to]=1,dfs(e[t].to,now,pos+1);
    }

}
int t1,t2,t3;
inline void init() {
    n=qr();
    m=qr();
    memset(ans,0x3f,sizeof ans);
    RP(t,1,m) {
        t1=qr();
        t2=qr();
        data[t].to=t1;
        data[t].fr=t2;
        data[t+m].fr=t1;
        data[t+m].to=t2;
        data[t].num=t;
        data[t+m].num=t;
    }
    sort(data+1,data+m+m+1,cmp);
    RP(t,1,m+m)
    add(data[t].fr,data[t].to,data[t].num);
    if(m==n-1) {
        dfs(1,0,1);
        RP(t,1,n)
        cout<<dfn[t]<<' ';
        cout<<endl;
        return;
    } else {
        RP(t,1,m) {
            top=0;
            better=0;
            memset(usd,0,sizeof usd);
            can[t]=1;
            dfs(1,0,1);
            can[t]=0;
            if(top==n) {
                RP(t,1,n) {
                    if(dfn[t]!=ans[t]) {
                        if(dfn[t]<ans[t])
                            better=1;
                        break;
                    }
                }
            }
            if(better&&top==n)
                RP(t,1,n)
                ans[t]=dfn[t];
        }
    }
    RP(t,1,n)
    cout<<ans[t]<<' ';
    cout<<endl;
    return;
}




int main() {
//    freopen("travel.in","r",stdin);
//    freopen("travel.out","w",stdout);
    init();
    return 0;
}
上一篇:php 生成二维码


下一篇:字符加密 Valentino 函数 (伪分治)