[POJ 1639] Picnic Planning

[题目链接]

           http://poj.org/problem?id=1639

[算法]

        首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块

        设共有T个联通块,若T > K则无解,否则 :

        求出这些联通块的最小生成树,得到一棵最小T度生成树,我们尝试改动(K - T)条边,使得答案变得更小,具体过程如下 :

        枚举所有与1相连的边,若这条边不在当前的生成树中,我们用广度优先搜索求出生成树上1号节点到该条边的节点中最长的边,用这条边的权值减去枚举边的权值即为生成树权值和变小了多少,求出这个变小的最大值

        如果这个最大值大于0,将这个最大值对应的边从生成树中删除,并加入新的边,否则退出

        重复以上过程(K - T)次,即可

[代码]

        

#include <algorithm>  
#include <bitset>  
#include <cctype>  
#include <cerrno>  
#include <clocale>  
#include <cmath>  
#include <complex>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <ctime>  
#include <deque>  
#include <exception>  
#include <fstream>  
#include <functional>  
#include <limits>  
#include <list>  
#include <map>  
#include <iomanip>  
#include <ios>  
#include <iosfwd>  
#include <iostream>  
#include <istream>  
#include <ostream>  
#include <queue>  
#include <set>  
#include <sstream>  
#include <stdexcept>  
#include <streambuf>  
#include <string>  
#include <utility>  
#include <vector>  
#include <cwchar>  
#include <cwctype>  
#include <stack>  
#include <limits.h>
using namespace std;
#define MAXN 1010
struct Edge
{
        int u,v,w;
} e[MAXN],edge[MAXN][MAXN];
int i,j,n,w,k,tot,block,ans,mx;
int val[MAXN],size[MAXN],fa[MAXN],p[MAXN],belong[MAXN];
bool visited[MAXN],flag[MAXN];
int mst[MAXN][MAXN];
map<string,int> mp;
string u,v;
vector< int > a[MAXN];
pair<int,int> ps,new_e,tmp;

inline bool cmp(Edge a,Edge b)
{
        return a.w < b.w;
}
inline int get_root(int x)
{
        if (fa[x] == x) return x;
        return fa[x] = get_root(fa[x]);
}
inline void dfs(int u)
{
        int i,v;
        visited[u] = true;
        belong[u] = block;
        for (i = 0; i < a[u].size(); i++)
        {
                v = a[u][i];
                if (e[v].u == u && e[v].v != 1 && !flag[v]) 
                {
                        flag[v] = true;
                        edge[block][++size[block]] = e[v];
                        dfs(e[v].v);
                } else if (e[v].v == u && e[v].u != 1 && !flag[v]) 
                {
                        flag[v] = true;
                        edge[block][++size[block]] = e[v];
                        dfs(e[v].u);
                }
        }
}
inline void kruskal(int id)
{
        int i,su,sv;
        static int s[MAXN];
        for (i = 1; i <= n; i++) fa[i] = i;    
        sort(edge[id] + 1,edge[id] + size[id] + 1,cmp);    
        for (i = 1; i <= size[id]; i++)
        {
                su = get_root(edge[id][i].u);
                sv = get_root(edge[id][i].v);
                if (su != sv) 
                {
                        ans += edge[id][i].w;
                        mst[edge[id][i].u][edge[id][i].v] = edge[id][i].w;
                        mst[edge[id][i].v][edge[id][i].u] = edge[id][i].w;
                        fa[su] = sv;
                } 
        }
}
inline pair<int,int> bfs(int s)
{
        int i,cur,l,r,now,mx;
        static bool visited[MAXN];
        static pair<int,int> q[MAXN];
        static int pre[MAXN];
        bool found = false;
        pair<int,int> res;
        memset(visited,false,sizeof(visited));
        q[l = r = 1] = make_pair(s,0);
        visited[s] = true;
        pre[1] = -1;
        while (l <= r)
        {
                cur = q[l].first;
                for (i = 1; i <= n; i++)
                {
                        if (visited[i]) continue;
                        if (!mst[cur][i]) continue;
                        visited[i] = true;
                        q[++r] = make_pair(i,mst[cur][i]);
                        pre[r] = l;                    
                        if (i == 1)
                        {
                                found = true;
                                break;
                        }
                }
                if (found) break;
                l++;
        }
        if (!found) return make_pair(0,0);
        now = r; mx = 0;
        while (pre[now] != -1)
        {
                if (q[now].second > mx)
                {
                        mx = q[now].second;
                        res = make_pair(q[pre[now]].first,q[now].first);
                }
                now = pre[now];
        }
        return res;
}
int main() 
{
        
     cin.tie(0); cin
>> n; mp["Park"] = 1; tot = 1; for (i = 1; i <= n; i++) { cin >> u >> v >> w; if (!mp[u]) mp[u] = ++tot; if (!mp[v]) mp[v] = ++tot; e[i] = (Edge){mp[u],mp[v],w}; a[mp[u]].push_back(i); a[mp[v]].push_back(i); } scanf("%d",&k); visited[1] = true; for (i = 1; i <= n; i++) { if (e[i].u == 1 && !visited[e[i].v]) { block++; dfs(e[i].v); } if (e[i].v == 1 && !visited[e[i].u]) { block++; dfs(e[i].u); } } if (block > k) { printf("-1 "); return 0; } for (i = 1; i <= block; i++) kruskal(i); memset(val,0x3f,sizeof(val)); for (i = 1; i <= n; i++) { if (e[i].u == 1 && e[i].w < val[belong[e[i].v]]) { val[belong[e[i].v]] = e[i].w; p[belong[e[i].v]] = e[i].v; } else if (e[i].v == 1 && e[i].w < val[belong[e[i].u]]) { val[belong[e[i].u]] = e[i].w; p[belong[e[i].u]] = e[i].u; } } for (i = 1; i <= block; i++) { ans += val[i]; mst[1][p[i]] = val[i]; mst[p[i]][1] = val[i]; } for (i = 1; i <= k - block; i++) { mx = 0; ps = new_e = make_pair(0,0); for (j = 1; j <= n; j++) { if (e[j].u == 1 && !mst[1][e[j].v]) { tmp = bfs(e[j].v); if (mst[tmp.first][tmp.second] - e[j].w > mx) { ps = tmp; new_e = make_pair(e[j].v,e[j].w); mx = mst[tmp.first][tmp.second] - e[j].w; } } if (e[j].v == 1 && !mst[1][e[j].u]) { tmp = bfs(e[j].u); if (mst[tmp.first][tmp.second] - e[j].w > mx) { ps = tmp; new_e = make_pair(e[j].u,e[j].w); mx = mst[tmp.first][tmp.second] - e[j].w; } } } if (mx == 0) break; ans -= mx; mst[1][new_e.first] = new_e.second; mst[ps.first][ps.second] = 0; } printf("Total miles driven: %d ",ans); return 0; }

        

原文地址:https://www.cnblogs.com/evenbao/p/9377597.html