【图论】【刷题】蓝题

1>神经网络

绿题

为什么用拓扑?

1)必备条件:DAG
2)本题的公式上,显示需要计算出能连接到本点的,全部的边值*点值
故而当我开始推这个点时,他的所有先驱点的状态全部都要求完
这只能是topo_sort

#include<cstdio>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
int n,m;
const int N=103;
int c[N],in[N],sz[N];
struct node
{
    int v,w;
    node(int vv,int ww)
    { v=vv,w=ww; }
    node(){}
};
vector <node > g[N];
queue <int > q;

void topo_sort()
{
    while(!q.empty())
    {
        int t=q.front();q.pop();
        sz[t]=g[t].size() ;
        
        for(int i=0;i<sz[t];i++)
        {
            node v=g[t][i];
            if(c[t]>0) c[v.v ]+=c[t]*v.w ;
            if(--in[v.v ]==0) q.push(v.v );
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&c[i],&x);
        if(c[i]>0) q.push(i);
        else c[i]-=x;
    }
    int u,v,w;
    while(m--)
    {
        scanf("%d%d%d",&u,&v,&w);
        g[u].push_back(node(v,w)); 
        in[v]++;
    }
    
    topo_sort();
    bool fail=true;
    for(int i=1;i<=n;i++)
        if(!sz[i] && c[i]>0)
        {
            printf("%d %d\n",i,c[i]);
            fail=false;
        }
    if(fail) printf("NULL\n");
    return 0;
} 

2>校园网络

>难点:
DAG中,如何加入最少的边,使图中所有边都在一个强连通分量中
>试着从in,out的方面分析问题,
加边:入度+1,出度+1
>推测 :
缩点 后的任意有向图
若要向其中添加一些边,使得仅存一个强连通分量,
添加边的数目min= max(入度为0的点 , 出度为0的点)
>证明:(luogu)

一个任意DAG,必定是由多个链形成的,必然有起点u和终点v

我们先建立u->v的边,嗯链少了一条,变成了点,

入度为0的点-1,出度为0的点-1

重复以上步骤,

直到最后所有的入度为0的点,出度为0的点,都消失了,

再看看图,就没有链了,都是环,或者说最后只剩下一个强连通分量

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;

int n,sum;
const int N=10003;
vector <int > g[N];
int fa[N],sz[N],dfn[N],low[N],tt;
stack <int> s;
bool f[N];
void tarjan (int x)
{
    dfn[x]=low[x]=++tt;
    f[x]=true,s.push(x);
    
    sz[x]=g[x].size() ;
    for(int i=0;i<sz[x];i++)
    {
        int v=g[x][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(f[v])
            low[x]=min(low[x],low[v]);
    }
    
    if(dfn[x]==low[x])
    {
        ++sum;
        while(s.top()!=x)
            f[s.top()]=false,fa[s.top()]=sum,s.pop();
        
        f[x]=false,fa[x]=sum,s.pop() ;
    }
}

int in[N],out[N];//存sum节点的入度 
int main()
{
    scanf("%d",&n);
    int x;
    for(int i=1;i<=n;i++)
        while(~scanf("%d",&x) && x)
            g[i].push_back(x); 
    
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++)
    {
        int fu=fa[i],fv;
        for(int j=0;j<sz[i];j++)
        {
            int v=g[i][j];
            fv=fa[v];
            if(fu!=fv) in[fv]++,out[fu]++;
        }
    }
    
    int ans1=0,ans2=0;
    for(int i=1;i<=sum;i++)
    {
        if(!in[i]) ans1++;
        if(!out[i]) ans2++; 
    }
    printf("%d\n%d",ans1,max(ans1,ans2));
    
    return 0;
}

3>旅行计划

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11420155.html