zoukankan      html  css  js  c++  java
  • [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; }

            

  • 相关阅读:
    Unity热更新03-C#调用XLua-06-将Lua表 映射到C#的列表和字典
    Unity热更新03-C#调用XLua-05-C#调用Lua函数
    Unity热更新03-C#调用XLua-04-C#调用Lua全局变量
    Unity热更新03-C#调用XLua-03-LuaMgr
    Unity热更新03-C#调用XLua-02-用户自定义加载Lua脚本
    Unity热更新02-Lua基础-016-Lua垃圾回收
    Unity热更新02-Lua基础-015-Lua自带库
    Unity热更新02-Lua基础-014-Lua"面向对象"总结
    Unity热更新02-Lua基础-014-Lua初识"面向对象"
    Unity热更新02-Lua基础-013-Lua元表
  • 原文地址:https://www.cnblogs.com/evenbao/p/9377597.html
Copyright © 2011-2022 走看看