hihoCoder 1160 攻城略地 编程之美2015初赛第二场

来源:互联网 发布:linux dd windows u盘 编辑:程序博客网 时间:2024/05/01 19:03

这一题一共有两种做法,第一种是用并查集,算出删除每一条边带来的最小代价是多少,然后删除前k条边后,再计算后面n-k条边的代价。第二种是用连通分量+贪心。

根据题意,每一个连通分量只要攻占其代价最小的城市,即可攻占整个连通分量。因为删除道路只会使得连通分量有增无减,显然只删除k条道路最优。

对于一颗树而言,每删除一条边都会增加一个连通分量。为了减少代价,对于原始的图,我们开始会选择删除那些不会增加连通分量的边。n的节点的连通图,其生成树有n-1条边。非连通的图,其生成树们有n-connectedcnt条边,connectedcnt是连通分量的个数。最终的图有m-k条边,所以再删除n-connectedcnt-(m-k)条边时,每删一条都会增加一个连通分量,每个连通分量的代价又可以通过一个节点的代价代替。

先通过dfs求出连通分量的个数,并记录每个连通分量中代价最小的节点。之后忽略这些节点,按照代价从小到大排序并选择前n-connectedcnt-(m-k)个节点即可。PS:我用bfs就一直TLE是什么鬼,难道这又是水过去的算法?

#include<iostream>#include<stdio.h>#include<cstdio>#include<stdlib.h>#include<vector>#include<string>#include<cstring>#include<cmath>#include<algorithm>#include<stack>#include<queue>#include<ctype.h>#include<map>#include<time.h>#include<bitset>#include<set>#include<list>using namespace std;//hiho 1160const int maxn=1000010;const int INF=0x3f3f3f3f;int T;int n;int m;int k;int w[maxn];vector<int>mp[maxn];long long ans;bool vis[maxn];int val;int idx;int connectedcnt;void bfs(int st)//lead to TLE{//    val=INF;//    idx=0;    queue<int>q;    //while(!q.empty()) q.pop();    q.push(st);    while(!q.empty())    {        int tmp=q.front();        vis[tmp]=true;        if(val>w[tmp])        {            val=w[tmp];            idx=tmp;        }        q.pop();        for(int i=0;i<mp[tmp].size();i++)        {            int to=mp[tmp][i];            if(vis[to]==false)            {                q.push(to);                //vis[to]=true;            }        }    }}void dfs(int u){    vis[u]=true;//    val=INF;必须在递归外面设初值//    idx=0;    if(w[u]<val)    {        val=w[u];        idx=u;    }    for(int i=0;i<mp[u].size();i++)    {        int v=mp[u][i];        if(vis[v]==false)        {            dfs(v);        }    }}int main(){    freopen("input.txt","r",stdin);    scanf("%d",&T);    for(int ca=1;ca<=T;ca++)    {        scanf("%d %d %d",&n,&m,&k);        ans=0;        connectedcnt=0;        memset(w,0,sizeof(w));        //memset(mp,0,sizeof(mp));        memset(vis,false,sizeof(vis));        for(int i=1;i<=n;i++)        {            scanf("%d",&w[i]);            mp[i].clear();        }        for(int i=0;i<m;i++)        {            int a=0;            int b=0;            scanf("%d %d",&a,&b);            mp[a].push_back(b);            mp[b].push_back(a);        }        for(int i=1;i<=n;i++)        {            if(vis[i]==false)            {                val=INF;                //bfs(i);                dfs(i);                ans+=val;                w[idx]=INF;                connectedcnt++;            }        }        int remain=n-connectedcnt-m+k;        sort(w+1,w+n+1);        for(int i=1;i<=remain;i++)        {            ans+=w[i];        }        printf("Case #%d: %lld\n",ca,ans);    }    return 0;}


0 0
原创粉丝点击