POJ1639 Planificación de picnic Árbol de expansión mínimo con grado limitado

Título:

Encuentre el árbol de expansión mínimo que satisfaga el grado limitado de un punto.

respuesta:

Esta inscripción es realmente problemática. Independientemente del parque de puntos que limita el grado, el árbol de expansión mínimo se obtiene de los bloques conectados restantes, y el árbol de expansión mínimo solo se tiñe mientras que el primario está coloreado y los bordes utilizados en el proceso están etiquetados . Primero conecte el parque al borde más corto de cada bloque conectado. En este momento, el árbol de expansión no es óptimo. En este momento, solo los bordes restantes del parque pueden contribuir al resultado de la reducción, por lo que es suficiente juzgar si los bordes restantes del parque pueden reducir la contribución. Para un árbol, agregar un borde definitivamente formará un anillo. BFS sale de este anillo, encuentra el borde más grande y resta el borde agregado para hacer la contribución. Corre hasta que el grado del parque esté completo o el lado agregado no haya contribuido.

Código AC:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
#include <stack>
#include <cstring>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define lep(i,a,b) for(int i=(a);i>=(b);i--) 
#define lepp(i,a,b) for(int i=(a);i>(b);i--)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp make_pair
#define pb push_back 
#define fi first
#define se second
#define All(x) x.begin(),x.end() 
#define ms(a,b) memset(a,b,sizeof(a)) 
#define INF 0x3f3f3f3f
#define INFF 0x3f3f3f3f3f3f3f3f
#define multi int T;scanf("%d",&T);while(T--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=20+5;
const int mod=1e9+7;
const db eps=1e-6;                                                                            
const db pi=acos(-1.0);
int n,park,c[N],s,cnt,dis[N];
map<string,int>num;
int road[N][N],used[N][N],to[N];
struct edge{
    int u,v,w;
    bool operator < (const edge &A) const{
        return w<A.w;
    }
};
int bfs(int x,int &u,int &v){
    int pre[N];
    ms(pre,0);
    pre[x]=park;
    queue<int>q;
    q.push(x);
    while(q.size()){
        int cur=q.front();
        q.pop();
        if(cur==park) break;
        rep(i,1,cnt)
            if(used[cur][i]==1&&pre[i]==0){
                pre[i]=cur;
                q.push(i);
            }
    }
    int w=0,cur=park;
    while(pre[cur]!=park){
        if(w<road[cur][pre[cur]]){
            w=road[cur][pre[cur]];
            u=cur,v=pre[cur];
        }
        cur=pre[cur];
    }
    return w;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("D:\\work\\data.in","r",stdin);
    #endif
    int minn[N],n,bef[N];
    cin>>n;
    cnt=0;
    ms(road,INF);
    ms(dis,INF);
    ms(bef,0);
    rep(i,1,n){
        string s1,s2;
        int w;
        cin>>s1>>s2>>w;
        if(num.find(s1)==num.end()) num[s1]=++cnt;
        if(num.find(s2)==num.end()) num[s2]=++cnt;
        road[num[s1]][num[s2]]=road[num[s2]][num[s1]]=w;
        if(s1=="Park") park=num[s1];
        if(s2=="Park") park=num[s2];
    }
    int color=0,ans=0;
    c[park]=++color;
    rep(i,1,cnt){
        if(c[i]) continue;
        ++color;
        priority_queue<pii>q;
        q.push(mp(0,i));
        dis[i]=0;
        while(q.size()){
            int idx=q.top().second,w=-q.top().first;
            q.pop();
            if(c[idx]) continue;
            c[idx]=color;
            if(bef[idx]){
                used[bef[idx]][idx]=1;
                used[idx][bef[idx]]=1;
            }
            ans+=w;
            // q.pop();pop要在push之前,要不然对于最小生成树这种并不是单调的,可能pop掉刚push的
            rep(j,1,cnt){
                if(c[j]) continue;
                if(dis[j]>road[idx][j]){
                    dis[j]=road[idx][j];
                    bef[j]=idx;
                    q.push({-dis[j],j});
                }  
            }
        }
    }
    ms(minn,INF);
    minn[c[park]]=0;
    rep(i,1,cnt){
        if(minn[c[i]]>road[park][i]){
            minn[c[i]]=road[park][i];
            to[c[i]]=i;
        }
    }
    rep(i,2,color){
        ans+=minn[i];
        used[park][to[i]]=used[to[i]][park]=1;
    }
    cin>>s;
    rep(i,1,s-color+1){
        edge e,maxn;
        int pos;
        maxn.w=0;
        rep(j,1,cnt){
            if(used[park][j]==1||road[park][j]==INF) continue;
            e.w=bfs(j,e.u,e.v)-road[park][j];
            if(e.w>maxn.w){maxn=e,pos=j;} 
        }
        if(maxn.w<=0) break;
        else{
            ans-=maxn.w;
            used[park][pos]=used[pos][park]=1;
            used[maxn.u][maxn.v]=used[maxn.v][maxn.u]=0;
        }
    }
    cout<<"Total miles driven: "<<ans<<endl;
}

 

Supongo que te gusta

Origin blog.csdn.net/Luowaterbi/article/details/112910866
Recomendado
Clasificación