POJ 3538/Codeforces 100078D:Domestic Networks 解题报告

点击这里进入题目
题意:有N个顶点M条边,每一条边都有相应的长度,你有长度为5和长度为6的线,你要用它来覆盖这些边,使花费最小。


思路:一个图上要求最小的花费,很明显要先处理最小生成树


AC程序

//库省略
using namespace std;
const int maxn=10005;
int n,m,k;
int fa[maxn];
int mst[maxn];
int num5,num6,cost5,cost6,i5=5,i6=6;
bool vis[maxn];
set<int> edge5,edge6;
int dp[maxn];
struct edge
{
    int x,y,l,id;
} e[maxn];
bool cmp(edge a,edge b)
{
    return a.l<b.l;
}
int findfa(int x)
{
    if(fa[x]==x)
    return x;
    else
    return fa[x]=findfa(fa[x]);
}
void MST()
{
    k=0;
    for(int i=0;i<m;i++)
    {
        int u=e[i].x,v=e[i].y;
        int fu=findfa(u),fv=findfa(v);
        if(fu!=fv)
        {
            fa[fu]=fv;
            mst[k++]=i;
        }
    }
}
void solve1()
{
    if(cost5>cost6)
    {
        swap(num5,num6);
        swap(cost5,cost6);
        swap(i5,i6);
    }
}
int main()
{
    freopen("domestic.in","r",stdin);
    freopen("domestic.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    for(int i=0;i<m;i++)
    {
        cin>>e[i].x>>e[i].y>>e[i].l;
        e[i].id=i+1;
    }
    sort(e,e+m,cmp);
    MST();
    cin>>cost5>>num5>>cost6>>num6;
    solve1();
    if(k!=n-1)
    {
        cout<<"Impossible"<<endl;
        return 0;
    }
    vis[0]=1;
    for(int i=0;i<k;i++)
    {
        int now=mst[i];
        int len=e[now].l;
        edge6.insert(now);
        for(int j=num5;j>=len;j--)
        {
            if(!vis[j] && vis[j-len])
            {
                vis[j]=1;
                dp[j]=mst[i];
            }
        }
    }
    int t=num5;
    while(!vis[t])
    t--;
    while(t>0)
    {
        edge5.insert(dp[t]);
        edge6.erase(dp[t]);
        t-=e[dp[t]].l;
    }
    int ans5=0,ans6=0;
    for(set<int>::iterator it=edge5.begin();it!=edge5.end();it++)
    ans5+=e[*it].l;
    for(set<int>::iterator it=edge6.begin();it!=edge6.end();it++)
    ans6+=e[*it].l;
    if(ans5<=num5 && ans6<=num6)
    {
        ll ans=(ans5*cost5)+(ans6*cost6);
        cout<<ans<<endl;
        for(set<int>::iterator it=edge5.begin();it!=edge5.end();it++)
        cout<<e[*it].id<<" "<<i5<<endl;
        for(set<int>::iterator it=edge6.begin();it!=edge6.end();it++)
        cout<<e[*it].id<<" "<<i6<<endl;
    }
    else
    {
        cout<<"Impossible"<<endl;
        return 0;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/NightRaven/p/9341826.html