2707: [SDOI2012]走迷宫 tarjan+高斯消元解期望方程组

SDOI2012啊,不错的一道题。
点数很多,我们不能直接高斯消元,而题目中提示了每个强连通分量的点数<=100,我们就可以先tarjan缩一下环。
先说一下无解的情况,如果有一个强连通分量到不了T,就可以在这个强连通分量内无限的走,答案为INF,dfs一下就可以解决。
考虑有解的情况,这就成了DAG上的期望DP问题,我们可以用fi表示从i走到T的期望步数,初始fT=0,那么fi可以在dfs的过程中由点i的后继转移而来,但是每个强连通分量内的点我们要用高斯消元来求,由于不超过100所以高斯消元完全可以解决。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define N 10005
#define M 1000005
using namespace std;
vector<int> V[N];
double f[N],a[105][105];
int n,m,S,T,tot,top,cnt,scc;
int dfn[N],low[N],belong[N],du[N],rank[N],vis[N],stack[N],head[N];
int list[M],next[M];
bool inset[N];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline void insert(int x,int y)
{
    next[++cnt]=head[x];
    head[x]=cnt;
    list[cnt]=y;
    du[x]++;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++tot;
    stack[++top]=x;
    inset[x]=true;
    for (int i=head[x];i;i=next[i])
        if (!dfn[list[i]])
        {
            tarjan(list[i]);
            low[x]=min(low[x],low[list[i]]);
        }
        else if (inset[list[i]]) low[x]=min(low[x],dfn[list[i]]);
    if (dfn[x]==low[x])
    {
        int i=-1;
        scc++;
        while (i!=x)
        {
            i=stack[top--];
            belong[i]=scc;
            rank[i]=V[scc].size();
            V[scc].push_back(i);
            inset[i]=false;
        }
    }
}
void dfs(int x)
{
    vis[x]=2;
    if (x==belong[T]) 
    {
        vis[x]=1;
        return;
    }
    for (int i=0;i<V[x].size();i++)
        for (int j=head[V[x][i]];j;j=next[j])
            if (belong[list[j]]!=x)
            {
                if (!vis[belong[list[j]]]) 
                    dfs(belong[list[j]]);
                if (vis[belong[list[j]]]==1) 
                    vis[x]=1;
            }
}
void get_ans(int x)
{
    int n=V[x].size();
    for (int i=0;i<n;i++)
        for (int j=head[V[x][i]];j;j=next[j])
            if (belong[list[j]]!=x&&!vis[belong[list[j]]]) 
                get_ans(belong[list[j]]);
    memset(a,0,sizeof(a));
    for (int i=0;i<n;i++)
    {
        a[i][i]=1;
        if (V[x][i]==T) continue;
        a[i][V[x].size()]=1;
        for (int j=head[V[x][i]];j;j=next[j])
            if (belong[list[j]]==x) 
                a[i][rank[list[j]]]-=1.0/du[V[x][i]];
            else a[i][V[x].size()]+=1.0/du[V[x][i]]*f[list[j]];
    }
    for (int i=0;i<n;i++)
    {
        double t=a[i][i];
        for (int j=0;j<=n;j++) 
            a[i][j]/=t;
        for (int j=0;j<n;j++)
            if (j!=i) 
            {
                double t=a[j][i];
                for (int k=0;k<=n;k++) 
                    a[j][k]-=t*a[i][k];
            }
    }
    for (int i=0;i<n;i++)
        f[V[x][i]]=a[i][n];
    vis[x]=1;
}
int main()
{
    n=read(); m=read(); S=read(); T=read();
    for (int i=1;i<=m;i++)
    {
        int u=read(),v=read();
        insert(u,v); 
    }
    for (int i=1;i<=n;i++)
        if (!dfn[i]) tarjan(i);
    memset(vis,0,sizeof(vis));
    dfs(belong[S]);
    for (int i=1;i<=scc;i++)
        if (vis[i]==2) 
        {
            puts("INF");
            return 0;
        }
    memset(vis,0,sizeof(vis));
    get_ans(belong[S]);
    printf("%.3lf\n",f[S]);
    return 0;
}
【电力系统】单机无穷大电力系统短路故障暂态稳定Simulink仿真(带说明文档)内容概要:本文档围绕“单机无穷大电力系统短路故障暂态稳定Simulink仿真”展开,提供了完整的仿真模型与说明文档,重点研究电力系统在发生短路故障后的暂态稳定性问题。通过Simulink搭建单机无穷大系统模型,模拟不同类型的短路故障(如三相短路),分析系统在故障期间及切除后的动态响应,包括发电机转子角度、转速、电压和功率等关键参数的变化,进而评估系统的暂态稳定能力。该仿真有助于理电力系统稳定性机理,掌握暂态过程分析方法。; 适合人群:电气工程及相关专业的本科生、研究生,以及从事电力系统分析、运行与控制工作的科研人员和工程师。; 使用场景及目标:①学习电力系统暂态稳定的基本概念与分析方法;②掌握利用Simulink进行电力系统建模与仿真的技能;③研究短路故障对系统稳定性的影响及提高稳定性的措施(如故障清除时间优化);④辅助课程设计、毕业设计或科研项目中的系统仿真验证。; 阅读建议:建议结合电力系统稳定性理论知识进行学习,先理仿真模型各模块的功能与参数设置,再运行仿真并仔细分析输出结果,尝试改变故障类型或系统参数以观察其对稳定性的影响,从而深化对暂态稳定问题的理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值