HDU 6041 I Curse Myself(二分+搜索)

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6041

【题目大意】

  给出一个仙人掌图,求第k小生成树

【题解】

  首先找到仙人掌图上的环,现在的问题就是从每个环中删除一个元素,
  求出删除元素总和中的第K大,我们发现通过限定第K大的大小,可以有效地搜索剪枝,
  限制的大小导致搜索出来的总和数量是具有单调性的,我们可以二分这个值,
  然后用搜索来定位第K大的大小。Thanks to Claris。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1010,M=2010,ALL=100010;
vector<int> v[N],w[N],a[N];
int Cas=1,n,m,K,st[N],pos,base,ans[ALL],dfn,f[N],fw[N],L,R,MID,t,cnt;
unsigned Ans;
bool cmpd(int x,int y){return x>y;}
bool cmp(const vector<int>&a,const vector<int>&b){return a[1]<b[1];}
void dfs(int x){
	  //printf("%d\n",x);
    st[x]=++dfn;
    for(int i=0;i<v[x].size();i++){
        int y=v[x][i],z=w[x][i];
        if(y==f[x])continue;
        if(!st[y]){f[y]=x;fw[y]=z;dfs(y);}
        else if(st[y]<st[x]){
            a[cnt].push_back(z);
            for(int j=x;j!=y;j=f[j])a[cnt].push_back(fw[j]);
            sort(a[cnt].begin(),a[cnt].end(),cmpd);
            base-=a[cnt][0];
            for(int j=a[cnt].size()-1;~j;j--)a[cnt][j]=a[cnt][0]-a[cnt][j];
            cnt++;
        }
    }
}
void dfs2(int x,int s){
    if(pos>=K||x==cnt)return;
    if(s+a[x][1]>MID)return;
    for(int i=1;i<a[x].size();i++){
        int sum=s+a[x][i];
        if(sum>MID)break;
        if(pos>=K)return;
        ans[++pos]=sum;
        dfs2(x+1,sum);
    }dfs2(x+1,s);
}
int cal(){
    LL ans=1;
    for(int i=0;i<cnt;i++){
        ans*=a[i].size();
        if(ans>1000000)return 1000000;
    }return ans;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            v[x].push_back(y); v[y].push_back(x);
            w[x].push_back(z); w[y].push_back(z);
            base+=z;
        }dfs(1);
        sort(a,a+cnt,cmp);
        scanf("%d",&K);
        K=min(K,cal());
        L=0,R=1000000000;
        while(L<=R){
            MID=(L+R)>>1; pos=1;
            dfs2(0,0);
            if(pos>=K)R=(t=MID)-1;
            else L=MID+1;
        }MID=t-1;
        pos=0;
        if(MID>=0)ans[++pos]=0;
        dfs2(0,0);
        for(int i=pos+1;i<=K;i++)ans[i]=t;
        sort(ans+1,ans+K+1);
        for(int i=1;i<=K;i++){
            ans[i]+=base;
            Ans+=1U*ans[i]*i;
        }printf("Case #%d: %u\n",Cas++,Ans);
        for(int i=1;i<=n;i++)f[i]=fw[i]=st[i]=0;
        for(int i=0;i<cnt;i++)a[i].clear();
        for(int i=1;i<=n;i++)v[i].clear(),w[i].clear();
        dfn=base=Ans=cnt=0;
    }return 0;
}
时间: 2024-10-03 04:12:52

HDU 6041 I Curse Myself(二分+搜索)的相关文章

hdu 6041 I Curse Myself 无向图找环+优先队列

I Curse Myself Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is a connected undirected graph with weights on its edges. It is guaranteed that each edge appears in at most one simple cy

HDU 3622 Bomb Game(二分+2-SAT)

Bomb Game Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5396    Accepted Submission(s): 1925 Problem Description Robbie is playing an interesting computer game. The game field is an unbounde

HDU 1312 ----- Red and Black 入门搜索 DFS解法

HDU 1312 ----- Red and Black  入门搜索  http://acm.hdu.edu.cn/showproblem.php?pid=1312 /*HDU 1312 ----- Red and Black 入门搜索 */ #include <cstdio> int n, m; //n行m列 int cnt, startx, starty; char mapp[25][25]; /*找一个连通的区域里可以走的块*/ void dfs(int x, int y){ if (x

hdu 3264 圆的交+二分

Open-air shopping malls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1822    Accepted Submission(s): 651 Problem Description The city of M is a famous shopping city and its open-air shopping

hdu 1399 Starship Hakodate-maru (暴力搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1399 题目大意:找到满足i*i*i+j*(j+1)*(j+2)/6形式且小于等于n的最大值. 1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int n; 9 while(scanf("%d",&n),n) 10 { 11 int j,

HDU 1885 Key Task 状态压缩+搜索

点击打开链接 Key Task Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1176    Accepted Submission(s): 462 Problem Description The Czech Technical University is rather old - you already know that it c

HDU 3081Marriage Match II(二分+并查集+网络流之最大流)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3081 有一段时间没写最大流的题了,这题建图居然想了好长时间...刚开始是按着最终的最大流即是做多轮数去想建图,结果根本没思路,后来想了想,可以用二分答案的思想来找最终答案.然后很明显的并查集,但是并查集学的略渣,居然卡在并查集上了..= =. 但是也不是并查集的事..是我建图的思想太正了,稍微用点逆向思维并查集就可以很好利用了. 建图思路是:建立一个源点与汇点,将女孩与源点相连,男孩与汇点相连,权值

hdu 6154 CaoHaha&#39;s staff 二分

题意: 一笔可以画一条长为1的边或者一条根号二的对角线 问围成一个面积是x的图形最少需要几条边 思路: 用公式直接二分 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(a) cerr<<#a<<"=="<<a<<endl 4 using namespace std; 5 typedef long long ll;

hdu 2899 Strange fuction (二分)

题目链接:http://acm.hdu.edu.cn/showproblem.pihp?pid=2899 题目大意:找出满足F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)的x值.注意精确度的问题. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 double y; 6 7 doub