四川省赛G.Party

题目链接:http://acm.bnu.edu.cn/v3/contest_show.php?cid=6865#problem/G
题意:n只青蛙,要么只喝绿茶,要么只喝红茶,要么两种茶都能接受,还有m个憎恶关系,互相憎恶的两只青蛙不能喝同一种茶,憎恶关系构成的图保证是一张二分图,当然,你还可以选择花费w[i]的代价删掉某只青蛙。问最少需要花费多少代价。

分析:题目问最小代价,给出的又是憎恶关系,容易想到最小割,关键是建图比较难想。首先,题目保证是二分图,可以对他黑白染色。假设没有两种茶都能喝的青蛙,那么只要对有边的且能喝茶种类相同的青蛙建边,流量连INF,跑最小割即可。现在考虑能喝两种茶的青蛙,假设他是白色的,那么可以将他拆成白红和白绿两个点,显然,白红只可能和黑红连边,白绿只可能和黑绿连边,因此我们可以考虑在左边放白绿/黑红,右侧放白红/黑绿,中间放置被拆成两个点的两种茶都能喝的青蛙,注意两种茶都能喝的青蛙之间可能有憎恶关系,我们把割边的流量设置在拆出的两个点之间,为了能让拆出两个点之间的流量起作用(选择这条边当割边就意味着删掉这只青蛙),需要从拆出的点中右侧的点连向左侧,这样就能保证删除起到了效果,具体还是要看下代码。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pi;
const int Inf=2e9,Maxn=1020*3,Maxe=320000;
int n,m,s,t,ne;
int val[Maxn],p[Maxn],col[Maxn],id[Maxn],h[Maxn];
int cur[Maxn];
vector<int>G1[Maxn];
vector<int>G[Maxn];
void dfs1(int u,int C)
{
    col[u]=C;
    for(int i=0;i<G1[u].size();i++)
    {
        int v=G1[u][i];if(col[v])continue;
        dfs1(v,3-C);
    }
}
pi e[Maxe];
void add(int u,int v,int w)
{
    e[ne]=pi(v,w);
    G[u].push_back(ne++);
    e[ne]=pi(u,0);
    G[v].push_back(ne++);
}
bool bfs()
{
    queue<int>q;
    for(int i=s;i<=t;i++)h[i]=Inf;
    h[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<G[u].size();i++)
        {
            int v=e[G[u][i]].first,w=e[G[u][i]].second;
            if(!w||h[v]!=Inf)continue;
            h[v]=h[u]+1;
            q.push(v);
        }
    }
    return h[t]!=Inf;
}
int dfs(int u,int a)
{
    if(u==t||!a)return a;
    int ret=0;
    for(int &i=cur[u];i<G[u].size();i++)
    {
        int v=e[G[u][i]].first,w=e[G[u][i]].second;
        if(h[v]!=h[u]+1||!w)continue;
        int b=dfs(v,min(a,w));
        e[G[u][i]].second-=b;
        e[G[u][i]^1].second+=b;
        ret+=b;
        a-=b;
    }
    return ret;
}
int dinic()
{
    for(int i=s;i<=t;i++)cur[i]=0;
    int ret=0;
    while(bfs())
    {
        for(int i=s;i<=t;i++)cur[i]=0;
        ret+=dfs(s,Inf);
    }
    return ret;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d",val+i);
        for(int i=1;i<=n;i++)G1[i].clear();
        for(int i=1;i<=n;i++)scanf("%d",p+i);
        for(int i=0;i<m;i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            G1[u].push_back(v);
            G1[v].push_back(u);
        }
        for(int i=1;i<=n;i++)col[i]=0;
        for(int i=1;i<=n;i++)
        {
            if(!col[i])dfs1(i,1);
        }
        //for(int i=1;i<=n;i++)printf("%d ",col[i]);puts("");
        ne=s=0;
        t=n+1;
        for(int i=1;i<=n;i++)
        {
            if(p[i]==3)
            {
                id[i]=t++;
            }
        }
        for(int i=s;i<=t;i++)G[i].clear();
        if(t>=Maxn)while(1);
        for(int i=1;i<=n;i++)
        {
            if(p[i]<3)
            {
                if(col[i]==p[i])
                {
                    //printf("u=%d\n",i);
                    add(s,i,val[i]);
                    for(int j=0;j<G1[i].size();j++)
                    {
                        int v=G1[i][j];
                        if(p[v]==3)add(i,v,Inf);
                        else if(p[v]!=col[v])add(i,v,Inf);
                    }
                }
                else
                {
                    add(i,t,val[i]);
                    //if(i==1)printf("t=%d\n",t);
                    for(int j=0;j<G1[i].size();j++)
                    {
                        int v=G1[i][j];
                        if(p[v]==3)add(id[v],i,Inf);
                    }
                }
            }
            else 
            {
                add(i,id[i],val[i]);
                for(int j=0;j<G1[i].size();j++)
                {
                    int v=G1[i][j];
                    if(p[v]==3)add(id[v],i,Inf);
                }
            }
        }
        //for(int i=1;i<=n;i++)printf("%d ",col[i]);puts("");
    /*  
        for(int i=s;i<=t;i++)
        {
            printf("point%d:\n",i);
            for(int j=0;j<G[i].size();j++)
            {
                printf("to=%d w=%d\n",e[G[i][j]].first,e[G[i][j]].second);
            }
            puts("");
        }
    */  
        printf("%d\n",dinic());
    }
}
【博士论文复现】【阻抗建模、验证扫频法】光伏并网逆变器扫频与稳定性分析(包含锁相环电流环)(Simulink仿真实现)内容概要:本文档是一份关于“光伏并网逆变器扫频与稳定性分析”的Simulink仿真实现资源,重点复现博士论文中的阻抗建模与扫频法验证过程,涵盖锁相环和电流环等关键控制环节。通过构建详细的逆变器模型,采用小信号扰动方法进行频域扫描,获取系统输出阻抗特性,并结合奈奎斯特稳定判据分析并网系统的稳定性,帮助深入理解光伏发电系统在弱电网条件下的动态行为与失稳机理。; 适合人群:具备电力电子、自动控制理论基础,熟悉Simulink仿真环境,从事新能源发电、微电网或电力系统稳定性研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握光伏并网逆变器的阻抗建模方法;②学习基于扫频法的系统稳定性分析流程;③复现高水平学术论文中的关键技术环节,支撑科研项目或学位论文工作;④为实际工程中并网逆变器的稳定性问题提供仿真分析手段。; 阅读建议:建议读者结合相关理论教材与原始论文,逐步运行并调试提供的Simulink模型,重点关注锁相环与电流控制器参数对系统阻抗特性的影响,通过改变电网强度等条件观察系统稳定性变化,深化对阻抗分析法的理解与应用能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值