P3959 [NOIP2017 提高组] 宝藏

 :::dfs指数级 所以 循环区间 提前判断函数 优化都有极大 效果 与分数

#include <cstdio>
using namespace std;

int a[55], l[55];
int cost[55][55];
int ans = 2147483645, tmp, n, m;

#define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
char BB[1 << 16], *S = BB, *T = BB;
inline int read () {
    int X = 0; char ch = 0;
    while(ch < 0 || ch > 9) ch = getchar();
    while(ch >= 0 && ch <= 9) X = X * 10 + ch - '0', ch = getchar();
    return X;
}

inline int min(int a, int b) {
    int c = (a - b) >> 31;
    return a ^ c | b ^ ~c;
}

inline void dfs(int e, int num) {
    if(num == n) {
        ans = min(tmp, ans);
        return;
    }
    if(tmp >= ans) return;
    for(int i = 1; i <= n; i ++) {//确定下一步扩展谁
        if(l[i]) continue;
        for(int j = 1; j <= n; j ++) {//由谁扩展
            if(cost[j][i] == 2147483645 || !l[j] || i == j) continue;
            tmp += l[j] * cost[j][i]; l[i] = l[j] + 1;
            dfs(i, num + 1);
            tmp -= l[j] * cost[j][i]; l[i] = 0;
        }
    }
}

int main() {
    int u, v;
    n = read(); m = read();
    for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= n; j ++)
    cost[i][j] = 2147483645;
    for(int i = 1; i <= m; i ++)
    u = read(), v = read(),
    cost[u][v] = cost[v][u] = min(cost[u][v], read());
    for(int i = 1; i <= n; i ++) {
        l[i] = 1; dfs(i, 1); l[i] = 0;
    }
    printf("%lld\n", ...);
    return 0;
}
#include<cstdio>
#include<iostream>
#include<algorithm>
//#include<queue>
//#include<vector>
//#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e3+10 ;

int n,m,c[maxn][maxn],g[maxn][maxn],d[maxn],vis[maxn],cnt,tmp,lev[maxn];
int p,ans=0x3f3f3f3f,res;

bool cmp(int a,int b){//sort 依据 
    return c[p][a]<c[p][b];
} 

void dfs(int x,int node)
{
    if(cnt>=n){
        ans=min(ans,res);
        return;
    }
    for(int i=x;i<=cnt;i++)
    {
        if(res+tmp*lev[vis[i]]>=ans) return;//>=
        for(int j=node;j<=d[vis[i]];j++)
        {
            if(lev[ g[vis[i]][j] ]==0){
                lev[g[vis[i]][j]]=lev[vis[i]]+1;
                vis[++cnt]=g[vis[i]][j];
                tmp-=c[vis[cnt]][ g[vis[cnt]][1] ];
                res+=lev[vis[i]]*c[vis[i]][vis[cnt]];//起点距离*线路长度 
                
                dfs(i,j+1);
                
                lev[g[vis[i]][j]]=0;
                tmp+=c[vis[cnt]][ g[vis[cnt]][1] ];
                res-=lev[vis[i]]*c[vis[i]][vis[cnt]];
                cnt--;
            }
        }
        node=1;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    //memsest(c,0x3f3f3f3f,sizeof(c));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            c[i][j]=0x3f3f3f3f;
            
    for(int i=1;i<=m;i++)
    {
        int u,v,val;cin>>u>>v>>val;
        if(c[u][v]<val) continue;
        if(c[u][v]==0x3f3f3f3f) g[u][++d[u]]=v,g[v][++d[v]]=u;
        c[u][v]=c[v][u]=val;
    }
    for(int i=1;i<=n;i++)
    {
        p=i;
        sort(g[i]+1,g[i]+1+d[i],cmp);//sort 对象 
        tmp+=c[i][ g[i][1] ];
    }
    for(int i=1;i<=n;i++)
    {
        lev[i]=1;cnt=1;res=0;
        vis[1]=i;
        tmp-=c[i][g[i][1]];
        
        dfs(1,1);
        
        tmp+=c[i][g[i][1]];
        lev[i]=0;
        //cnt vis
    }
    
    cout<<ans<<'\n';
    
    return 0;
}
AC

 

posted @ 2023-08-22 00:26  JMXZ  阅读(12)  评论(0)    收藏  举报