HDU - 4126 Genghis Khan the Conqueror

本文探讨了一道结合树形动态规划与最小生成树(MST)算法的复杂编程问题,通过解决成吉思汗将军哲别在征服国家Pushtuar时面临的通讯网络优化挑战,介绍了如何在图中寻找最小生成树,并在边权变动情况下快速计算新的最小生成树成本期望值。

HDU - 4126 Genghis Khan the Conqueror

树形dp+MST

题目描述
Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元太祖), was the founder of the Mongol Empire and the greatest conqueror in Chinese history. After uniting many of the nomadic tribes on the Mongolian steppe, Genghis Khan founded a strong cavalry equipped by irony discipline, sabers and powder, and he became to the most fearsome conqueror in the history. He stretched the empire that resulted in the conquest of most of Eurasia. The following figure (origin: Wikipedia) shows the territory of Mongol Empire at that time.
在这里插入图片描述

Our story is about Jebei Noyan(哲别), who was one of the most famous generals in Genghis Khan’s cavalry. Once his led the advance troop to invade a country named Pushtuar. The knights rolled up all the cities in Pushtuar rapidly. As Jebei Noyan’s advance troop did not have enough soldiers, the conquest was temporary and vulnerable and he was waiting for the Genghis Khan’s reinforce. At the meantime, Jebei Noyan needed to set up many guarders on the road of the country in order to guarantee that his troop in each city can send and receive messages safely and promptly through those roads.

There were N cities in Pushtuar and there were bidirectional roads connecting cities. If Jebei set up guarders on a road, it was totally safe to deliver messages between the two cities connected by the road. However setting up guarders on different road took different cost based on the distance, road condition and the residual armed power nearby. Jebei had known the cost of setting up guarders on each road. He wanted to guarantee that each two cities can safely deliver messages either directly or indirectly and the total cost was minimal.

Things will always get a little bit harder. As a sophisticated general, Jebei predicted that there would be one uprising happening in the country sooner or later which might increase the cost (setting up guarders) on exactly ONE road. Nevertheless he did not know which road would be affected, but only got the information of some suspicious road cost changes. We assumed that the probability of each suspicious case was the same. Since that after the uprising happened, the plan of guarder setting should be rearranged to achieve the minimal cost, Jebei Noyan wanted to know the new expected minimal total cost immediately based on current information.
输入
There are no more than 20 test cases in the input.
For each test case, the first line contains two integers N and M (1<=N<=3000, 0<=M<=N×N), demonstrating the number of cities and roads in Pushtuar. Cities are numbered from 0 to N-1. In the each of the following M lines, there are three integers x i, y i and c i(c i<=10 7), showing that there is a bidirectional road between x i and y i, while the cost of setting up guarders on this road is c i. We guarantee that the graph is connected. The total cost of the graph is less or equal to 10 9.

The next line contains an integer Q (1<=Q<=10000) representing the number of suspicious road cost changes. In the following Q lines, each line contains three integers X i, Y i and C i showing that the cost of road (X i, Y i) may change to C i (C i<=10 7). We guarantee that the road always exists and C i is larger than the original cost (we guarantee that there is at most one road connecting two cities directly). Please note that the probability of each suspicious road cost change is the same.
输出
For each test case, output a real number demonstrating the expected minimal total cost. The result should be rounded to 4 digits after decimal point.
样例输入
3 3
0 1 3
0 2 2
1 2 5
3
0 2 3
1 2 6
0 1 6
0 0
样例输出
6.0000
Hint
The initial minimal cost is 5 by connecting city 0 to 1 and city 0 to 2. In the first suspicious case, the minimal total cost is increased to 6;
the second case remains 5; the third case is increased to 7. As the result, the expected cost is (5+6+7)/3 = 6.
题意
给你一个图,有q次询问,每次询问如果替换一条边后最小生成树的大小是多少,求q次询问的平均值。(要替换的边的权一定不小于原来边权,替换只在当前次询问有效)
思路
首先找到一颗最小生成树,之后当要替换的边不在最小生成树里的话,当前的最小生成树就直接是最小生成树的值。如果要替换的边在最小生成树里面的话,比如(u,v)边是要替换的边,将(u,v)删掉之后就会形成两个子树,就需要找出一条能连接这两个子树最小的那条边,那我们就可以实现处理出最小生成树上每条边的最小替换值。
dfs(u,fa,p)的含义为以u为跟的子树中所有节点v连接到节点p最短距离的边。所以dp[u][v]=dp[v][u]=min(dp[u][v],dfs(v,u,p));

而dfs的值由u的所有儿子v节点连接到p的最小值res=min(tmp,res);&&u节点到p节点的值取min得if(p!=fa)
res=min(res,G[u][p]); 这样得到的就是u为根节点的子树到p的最小值。。之后枚举p(1-n)可得替换i-j的边再次成MST需要dp[i][j]。
好题
3目运算符时间快&&关闭输入流确实比scanf快

 #pragma GCC optimize(3,"Ofast","inline")  	//G++
#include<bits/stdc++.h>

#define TEST freopen("C:\\Users\\hp\\Desktop\\ACM\\in.txt","r",stdin);
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fcout cout<<setprecision(4)<<fixed

using namespace std;
typedef long long ll;

const int inf=0x3f3f3f3f;
const int INF=0x7fffffffffffffff;
const int mod=1e9+7;
const int maxn = 3e3+5;

int n,m,q;
ll MST;
struct node
{
    int x,y,val;
    bool friend operator < (const node a,const node b)
    {
        return a.val<b.val;
    }
} a[maxn*maxn];
int re[maxn],G[maxn][maxn],vis[maxn][maxn],dp[maxn][maxn];
vector<int>edge[maxn];
void add(int x,int y)
{
    vis[x][y]=vis[y][x]=1;
    edge[x].push_back(y);
    edge[y].push_back(x);
}
void init()
{
    MST=0;
    for(int i=1; i<=n; i++)
    {
        edge[i].clear();
        re[i]=i;
        for(int j=1; j<=n; j++)
        {
            dp[i][j]=G[i][j]=inf;
            vis[i][j]=0;
        }
    }
    for(int i=1; i<=m; i++)
    {
        int x,y,val;
        cin>>x>>y>>val;
        x++,y++;
        G[x][y]=G[y][x]=val;
        a[i]=node{x,y,val};
    }
}
int fin(int x)
{
    return re[x]==x?x:re[x]=fin(re[x]);
}
void kruscal()
{
    sort(a+1,a+m+1);
    int cnt=0;
    for(int i=1; i<=m; i++)
    {
        int xx=fin(a[i].x),yy=fin(a[i].y);
        if(xx!=yy)
        {
            cnt++;
            re[xx]=yy;
            MST+=a[i].val;
            add(a[i].x,a[i].y);
        }
        if(cnt==n-1) break;
    }
}
int dfs(int u,int fa,int p)
{
    int res=inf;
    for(auto v:edge[u])
    {
        if(v==fa) continue;
        int tmp=dfs(v,u,p);
        res=min(tmp,res);
        dp[u][v]=dp[v][u]=min(dp[u][v],tmp);
    }
    if(p!=fa)
        res=min(res,G[u][p]);
    return res;
}
main()
{
    ios;
    while(cin>>n>>m&&(n||m))
    {
        init();
        kruscal();
        for(int i=1; i<=n; i++)
        {
            dfs(i,0,i);
        }
        cin>>q;
        int tmp_q=q;
        ll ans=0;
        while(q--)
        {
            int x,y,val;
            cin>>x>>y>>val;
            x++,y++;
            vis[x][y]?ans+=MST-G[x][y]+min(dp[x][y],val):ans+=MST;
        }
        fcout<<ans*1.0/tmp_q<<"\n";
    }
}
### 关于HDU - 6609 的题目解析 由于当前未提供具体关于 HDU - 6609 题目的详细描述,以下是基于一般算法竞赛题型可能涉及的内容进行推测和解答。 #### 可能的题目背景 假设该题目属于动态规划类问题(类似于多重背包问题),其核心在于优化资源分配或路径选择。此类问题通常会给出一组物品及其属性(如重量、价值等)以及约束条件(如容量限制)。目标是最优地选取某些物品使得满足特定的目标函数[^2]。 #### 动态转移方程设计 如果此题确实是一个变种的背包问题,则可以采用如下状态定义方法: 设 `dp[i][j]` 表示前 i 种物品,在某种条件下达到 j 值时的最大收益或者最小代价。对于每一种新加入考虑范围内的物体 k ,更新规则可能是这样的形式: ```python for i in range(n): for s in range(V, w[k]-1, -1): dp[s] = max(dp[s], dp[s-w[k]] + v[k]) ``` 这里需要注意边界情况处理以及初始化设置合理值来保证计算准确性。 另外还有一种可能性就是它涉及到组合数学方面知识或者是图论最短路等相关知识点。如果是后者的话那么就需要构建相应的邻接表表示图形结构并通过Dijkstra/Bellman-Ford/Floyd-Warshall等经典算法求解两点间距离等问题了[^4]。 最后按照输出格式要求打印结果字符串"Case #X: Y"[^3]。 #### 示例代码片段 下面展示了一个简单的伪代码框架用于解决上述提到类型的DP问题: ```python def solve(): t=int(input()) res=[] cas=1 while(t>0): n,k=list(map(int,input().split())) # Initialize your data structures here ans=find_min_unhappiness() # Implement function find_min_unhappiness() res.append(f'Case #{cas}: {round(ans)}') cas+=1 t-=1 print("\n".join(res)) solve() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值