hdu 4126 MST的最佳替换边 —— 2011ACM福州赛区F题

原创 2012年03月21日 11:49:17

这题AC的挺不容易的,花了很多时间,但是我觉得做完一道这种题能学到很多东西,绝对不是刷20道甚至是100道水题能比的~

这题的关键是在求出最小生成树之后求出去掉生成树任意一条边后剩下的两颗树的距离,可以证明这个距离就是最佳替换边的长度,而把原来最小生成树的边换成最佳替换边后所得到的生成树就是原图中去掉那条边的最小生成树,这个用反正法可以证明,如果新得到的树不是最小生成树可以推出原来的树也不是最小生成树,要画图我就不详细证了。

然后求两颗树之间的最小距离我是用树状dp实现的,挺麻烦的,dp的方法有很多,只要把复杂度控制在O(n2)之内就可以了~~

好吧,哥继续搞sgu了 ~

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;

#ifdef _WIN32
#define i64 __int64
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
#define i64 long long
#define out64 "%lld\n"
#define in64 "%lld"
#endif

#define FOR(i,a,b)      for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a)         for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a)        for( int i = (a)-1 ; i >= 0 ; i --)
#define S64(a)          scanf(in64,&a)
#define SS(a)           scanf("%d",&a)
#define LL(a)           ((a)<<1)
#define RR(a)           (((a)<<1)+1)
#define SZ(a)           ((int)a.size())
#define PP(n,m,a)       puts("---");FF(i,n){FF(j,m)cout << a[i][j] << ' ';puts("");}
#define pb              push_back
#define CL(Q)           while(!Q.empty())Q.pop()
#define MM(name,what)   memset(name,what,sizeof(name))
#define read            freopen("in.txt","r",stdin)
#define write           freopen("out.txt","w",stdout)

const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-10;
const double pi = acos(-1.0);
const int maxn = 3011;

struct zz
{
    int from;
    int to;
    int cost;
    bool operator < (const zz & cmp ) const
    {
        return cost > cmp.cost;
    }
}zx;

priority_queue<zz>q;
vector<zz>g[maxn];
vector<int>t[maxn];

bool hash[maxn][maxn];
bool vis[maxn];
bool ist[maxn][maxn];
bool fd[maxn][maxn];
int d[maxn][maxn];
int dp[maxn][maxn];
int ex[maxn];
int f[maxn];
int n,m,qq;
int mst;

void init()
{
    FF(i,maxn)
    {
        g[i].clear();
        t[i].clear();
    }
    CL(q);
    MM(hash,false);
    MM(fd,false);
    return ;
}

int prim()
{
    int ans = 0;
    CL(q);
    MM(vis,false);
    MM(f,-1);
    MM(ist,false);
    vis[0]=true;
    FF(i,g[0].size())
    {
        q.push(g[0][i]);
    }
    int now,to;
    int temp;
    FOR(i,1,n-1)
    {
        while(true)
        {
            zx = q.top();
            q.pop();
            if(vis[zx.to])
            {
                continue;
            }
            f[zx.to] = zx.from;
            ans += zx.cost;
            ist[zx.from][zx.to] = ist[zx.to][zx.from] = true;
            t[zx.from].push_back(zx.to);
            vis[zx.to]=true;
            now = zx.to;
            FF(i,g[now].size())
            {
                to = g[now][i].to;
                if(!vis[to])
                {
                    q.push(g[now][i]);
                }
            }
            break;
        }
    }
    return ans;
}

void dfs(short now)
{
    vis[now] = true;
    short i;
    for(i=0;i<n;i++) if(vis[i])
    {
        fd[now][i] =true;
    }
    short to;
    for(i=0;i<g[now].size();i++)
    {
        to = g[now][i].to;
        if(!vis[to] && f[to]!=now)
        {
            dp[now][to] = g[now][i].cost;
        }
    }
    for(i=0;i<t[now].size();i++)
    {
        to = t[now][i];
        dfs(to);
    }
    vis[now]=false;
    return ;
}

int dpst(short now,short id)
{
    short to;
    if(fd[id][now])
    {
        FF(i,t[now].size())
        {
            to = t[now][i];
            dpst(to,id);
        }
    }
    else
    {
        int temp = inf;
        FF(i,t[now].size())
        {
            to = t[now][i];
            temp = min( dpst(to,id) , temp );
        }
        dp[id][now] = temp = min(dp[id][now],temp);
        return temp;
    }
}

void final()
{
    FF(i,n) FF(j,n) if(!fd[j][i])
    {
        ex[i] = min(ex[i],dp[j][i]);
    }
    return ;
}

void start()
{
    FF(i,maxn) ex[i] = inf;
    mst = prim();
    FF(i,maxn) FF(j,maxn)
    {
        dp[i][j] = inf;
    }
    MM(vis,false);
    dfs(0);
    FF(i,n)
    {
        dpst(0,i);
    }
    final();
    return ;
}

int main()
{
    while(cin>>n>>m)
    {
        if(!n && !m)
        {
            break;
        }
        init();
        FF(i,m)
        {
            SS(zx.from);
            SS(zx.to);
            SS(zx.cost);
            hash[zx.from][zx.to] = hash[zx.to][zx.from] = true;
            d[zx.from][zx.to] = d[zx.to][zx.from] = zx.cost;
            g[zx.from].push_back(zx);
            swap(zx.from,zx.to);
            g[zx.from].push_back(zx);
        }
        start();
        cin>>qq;
        int x,y,z;
        double ans=0.0;
        double add;
        double qx = qq;
        while(qq--)
        {
            SS(x);
            SS(y);
            SS(z);
            if(!ist[x][y])
            {
                ans += mst;
            }
            else
            {
                if(f[x] == y)
                {
                    add = min(ex[x],z) - d[x][y];
                }
                else
                {
                    add = min(ex[y],z) - d[x][y];
                }
                ans += add + mst;
            }
        }
        ans /= qx;
        printf("%.4lf\n",ans);
    }
    return 0;
}



HDU 5483 Nux Walpurgis 图的最小生成树中必要的边的数目 动态MST问题

裸的动态MST 两次dp就可以辣 #include #include #include #include using namespace std; #define scan(x) scanf(...
  • u011775691
  • u011775691
  • 2015年09月26日 23:02
  • 498

2011年福州赛区A题 Xiangqi 模拟题

#include #include #include #define cl(xx,yy) memset((xx),(yy),sizeof((xx))) using namespace std; ...
  • Jianquan520
  • Jianquan520
  • 2013年09月05日 11:11
  • 636

hdu 最大流水题集锦。。。

源自--------------------------------Ice_Crazy(死之前应该会继续更新的。。。) 网络流水题:hdu1532、hdu3549、hdu2732(拆点、经典题...
  • Ice_Crazy
  • Ice_Crazy
  • 2013年08月05日 18:22
  • 3710

hdu 1226 搜索好题 帅呆了的题目

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S...
  • hnust_xiehonghao
  • hnust_xiehonghao
  • 2013年05月30日 11:58
  • 1776

HDU 5012 Dice (2014年西安赛区网络赛F题)

1.题目描述:点击打开链接 2.解题思路:本题利用BFS解决。本题是一道隐式图搜索题目,不过本题的状态扩展比较简单,直接用常量数组即可搞定,然后就可以进行扩展了,比较简单就不再详细叙述过程了。 3.代...
  • u014800748
  • u014800748
  • 2015年09月12日 22:59
  • 257

HDU 5002 Tree (2014年鞍山赛区网络赛F题)

1.题目描述:点击打开链接 2.解题思路:LCT的模板题 3.代码: #include #include #include #include #include using names...
  • u014800748
  • u014800748
  • 2015年08月28日 01:44
  • 919

HDU 5532 2015ACM-ICPC长春赛区现场赛F题

Almost Sorted ArrayTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Oth...
  • still_foolish
  • still_foolish
  • 2016年10月14日 21:53
  • 163

HDU6040(思维题)

题意:通过题目所给函数求出a数组,然后根据b数组排a数组。ai必须是a数组中第(bi+1)大的数。 分析:先通过下标对b数组排序。然后扫一遍b数组,如果相邻两个位置b相同,那么就还选上一个a(因为n可...
  • nucshiyilang
  • nucshiyilang
  • 2017年07月25日 21:24
  • 745

hdu 1276 士兵队列训练问题(水题)

士兵队列训练问题 Problem Description 某部队进行新兵队列训练,将新兵从一
  • tju_peter
  • tju_peter
  • 2017年01月14日 14:40
  • 132

【基础编程】hdu题目分类

hdu题目分类(转) http://apps.hi.baidu.com/share/detail/17053154 1001 整数求和 水题 1002 C语言实验题——两个数比较 水题 10...
  • XGsilence
  • XGsilence
  • 2016年10月10日 17:07
  • 761
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hdu 4126 MST的最佳替换边 —— 2011ACM福州赛区F题
举报原因:
原因补充:

(最多只允许输入30个字)