2017 Multi-University Training Contest - Team 1 1009 I Curse Myself 【思维 + 仙人掌图】
2017-07-31 22:11
351 查看
传送门
//题意: 给一幅仙人掌图, 问前k小的生成树的权值, 结合题目所给式子.
//思路:由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉. 所以问题就变为有 M 个集合,每个集合里面都有一堆数字, 要从每个集合中选择一个恰好一个数加起来. 求所有的这样的和中,前 K 大的是哪些. 这就是一个经典问题了. ( 然而我并不知道 )
多校第一场题解
//收获: 点双联通就不说了, 难点在于求前K大, 这里是多个集合, 看了题解才知道原来是这样, 先前两个合并, 然后和后面的每一个集合合并. 想法很棒, 这次长知识了, 处理的也很好.
代码就贴标程把, 我自己写的vector 一直被卡, 这个标程的vector也是3950ms左右. 其实我自己的改的跟标程差不多了, 还是T. 所以还是贴标程.
重要的是这道题的处理思想 !
AC Code
//题意: 给一幅仙人掌图, 问前k小的生成树的权值, 结合题目所给式子.
//思路:由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉. 所以问题就变为有 M 个集合,每个集合里面都有一堆数字, 要从每个集合中选择一个恰好一个数加起来. 求所有的这样的和中,前 K 大的是哪些. 这就是一个经典问题了. ( 然而我并不知道 )
多校第一场题解
//收获: 点双联通就不说了, 难点在于求前K大, 这里是多个集合, 看了题解才知道原来是这样, 先前两个合并, 然后和后面的每一个集合合并. 想法很棒, 这次长知识了, 处理的也很好.
vector<int> W; void merge(vector<int> &V , vector<int> B) { priority_queue< opt > Q; for (int i = 0 ; i < B.size() ; ++ i) { Q.push((opt) {V[0] + B[i] , i , 0}); } //首先把当前第一个答案数组中的数(V中的最大)一一加上新加的数丢进队列. //x: i 代表新加的数组的下标, y: 0 是当前答案数组加的下标. vector<int > v; W.resize(0); //目标就是维护一个前K大的序列. while (W.size() < K && !Q.empty()) { auto it = Q.top(); Q.pop(); W.push_back(it.w); if (it.y + 1 < V.size()) { //有下一个可以推. ++ it.y; //就是把第二个可能是最大的在推进队列. Q.push((opt) {B[it.x] + V[it.y] , it.x , it.y}); } } V = W; }
代码就贴标程把, 我自己写的vector 一直被卡, 这个标程的vector也是3950ms左右. 其实我自己的改的跟标程差不多了, 还是T. 所以还是贴标程.
重要的是这道题的处理思想 !
AC Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n , m , K;
struct opt {
int w , x , y;
bool operator < (const opt& R) const {
return w < R.w;
}
};
vector<int> W; void merge(vector<int> &V , vector<int> B) { priority_queue< opt > Q; for (int i = 0 ; i < B.size() ; ++ i) { Q.push((opt) {V[0] + B[i] , i , 0}); } //首先把当前第一个答案数组中的数(V中的最大)一一加上新加的数丢进队列. //x: i 代表新加的数组的下标, y: 0 是当前答案数组加的下标. vector<int > v; W.resize(0); //目标就是维护一个前K大的序列. while (W.size() < K && !Q.empty()) { auto it = Q.top(); Q.pop(); W.push_back(it.w); if (it.y + 1 < V.size()) { //有下一个可以推. ++ it.y; //就是把第二个可能是最大的在推进队列. Q.push((opt) {B[it.x] + V[it.y] , it.x , it.y}); } } V = W; }
int pre
, mcnt;
struct edge {
int x , w , next;
} e[N << 2];
vector<int> res;
int dfn
, low
, ncnt;
stack<int> S;
void dfs(int x , int fa) {
dfn[x] = low[x] = ++ ncnt;
for (int i = pre[x] ; ~i ; i = e[i].next) {
int y = e[i].x;
if (!dfn[y]) {
S.push(i);
dfs(y , i ^ 1);
low[x] = min(low[x] , low[y]);
if (low[y] > dfn[x]) {}//(x , y) is bridge
if (low[y] >= dfn[x]) {
int j;
vector<int> V;
do {
j = S.top();
S.pop();
V.push_back(e[j].w);
} while (j != i);
if (V.size() > 1) {
//cout << V.size() << endl;
//for (auto &x : V) cout << x << ' '; cout << endl;
merge(res , V);
}
}
} else if (i != fa && dfn[y] < dfn[x])
S.push(i) , low[x] = min(low[x] , dfn[y]);
}
}
void work() {
memset(pre , -1 , sizeof(pre));
mcnt = ncnt = 0;
int sum = 0;
for (int i = 0 ; i < m ; ++ i) {
int x , y , z;
scanf("%d%d%d" , &x , &y , &z);
e[mcnt] = (edge) {y , z , pre[x]} , pre[x] = mcnt ++;
e[mcnt] = (edge) {x , z , pre[y]} , pre[y] = mcnt ++;
sum += z;
}
scanf("%d" , &K);
res.resize(0); //因为和第一个集合合并,此时res里面没有数.
res.push_back(0); //所以需要先推进一个0做预处理.
memset(dfn , 0 , sizeof(dfn));
dfs(1 , 0);
int w = 0;
for (int i = 0 ; i < res.size() ; ++ i) {
w += (i + 1) * (sum - res[i]);
}
static int ca = 0;
printf("Case #%d: %u\n" , ++ ca , w);
}
int main() {
res.reserve(100001);
W.reserve(100001);
while (~scanf("%d%d" , &n , &m)) {
work();
}
}
相关文章推荐
- hdu 6041 I Curse Myself [2017 Multi-University Training Contest - Team 1]
- HDU 2017 Multi-University Training Contest - Team 4 1009 1011
- HDU-6105 Gameia - 2017 Multi-University Training Contest - Team 6(思维之找规律或二分图最大匹配)
- HDU-6058 Kanade's sum - 2017 Multi-University Training Contest - Team 3(思维+模拟链表)
- 2017 Multi-University Training Contest - Team 1 1006 Function(思维 循环节)
- HDU6069 2017 Multi-University Training Contest - Team 4 1003 Counting Divisors(唯一分解定理+思维优化)
- 2017 Multi-University Training Contest - Team 2 1009 HDU 6053 TrickGCD(分段 容斥)
- HDU-6060 RXD and dividing - 2017 Multi-University Training Contest - Team 3(思维+最小斯坦纳树)
- 2017 Multi-University Training Contest - Team 5 1008 【思维 + 01背包思想】
- 2017 Multi-University Training Contest - Team 1 B - Balala Power! (思维代码能力,贪心)
- HDU-6140 Killer Names - 2017 Multi-University Training Contest - Team 8(思维)
- 2017 Multi-University Training Contest - Team 3 1005 RXD and dividing 【思维 + 贪心】
- 2017 Multi-University Training Contest - Team 4:1009&hdu6075、Questionnaire
- 2017 Multi-University Training Contest - Team 2,HDU 6045 Is Derek lying?(思维水题)
- HDU 6055 Regular polygon(计算几何+思维)——2017 Multi-University Training Contest - Team 2
- 2017 Multi-University Training Contest - Team 6 1008 Kirinriki【思维题 + 尺取】
- 2017 Multi-University Training Contest - Team 4 1009 Questionnaire
- 2017 Multi-University Training Contest - Team 1 1006 【思维+强联通找环】
- hdu 6045 简单的思维题 2017 Multi-University Training Contest - Team 2
- HDU 6127 Hard challenge(思维+计算几何)——2017 Multi-University Training Contest - Team 7