图论刷题记录

[NOIP2003 提高组] 神经网络 - 洛谷P1038 [NOIP2003 提高组] 神经网络

容鄙人说一下,这是鄙人刷过最caodan的一个题,我就没见过这么刁钻的数据..

传入层的出度可以是0,但是,他依然可以传导,并且还应该被当做答案输出

第二,传入层一开始就是激发状态!并且不能减u  我就没见过这么caodan

题目似乎也说了

 意思是传入层根本没有j属于i,那么按这个推ci就是负数,也就无法传导,所以...就很离谱的不要减u才正确,关键是题目根本没有挑明。。

# include <iostream>
# include<vector>
# include<queue>

using namespace std;

int ru[110];
int chu[110];

int f[110][110];

vector<int>v[110];

int c[110],u[110];
queue<int>q;
int main()
{
    int n,m;

    cin>>n>>m;

    for(int i=1; i<=n; i++)
    {
       cin>>c[i]>>u[i];
       
      
    }

    for(int i=1; i<=m; i++)
    {
        int x,y,z;

        cin>>x>>y>>z;

        f[x][y]=z;

        v[x].push_back(y);

        chu[x]++;

        ru[y]++;


    }

    for(int i=1; i<=n; i++)
    {
        if(ru[i]==0)
        {
            q.push(i);

            c[i]-=u[i];
        }
        else
        {
            c[i]-=u[i];

        }
    }


    while(!q.empty())
    {
        int now=q.front();

        q.pop();

        for(auto it:v[now])
        {

            ru[it]--;

            c[it]+=c[now]*f[now][it];

            if(ru[it]==0&&c[it]>0)
            {
                q.push(it);
            }
        }
    }
    int flag=0;

    for(int i=1; i<=n; i++)
    {
        if(chu[i]==0&&c[i]>0)
        {
            cout<<i<<" "<<c[i]<<endl;

            flag=1;
        }
    }

    if(!flag)
    {
        cout<<"NULL";


    }


    return 0;
}
[NOIP2013]车站分级

把等级低的往等级高的连一条有向边即可,拓扑DP

#include <iostream>
# include<algorithm>
# include<cstring>
# include<vector>
# include<queue>


using namespace std;

typedef long long int ll;

int du[1010];

int st[1010];

bool book[1010];

bool edge[1010][1010];

vector<int>v[1010];

int ans[1010];

int dp[1010];

queue<int>q;
int main()
{
    int n,m;

    cin>>n>>m;

    while(m--)
    {
        int t;

        cin>>t;


        for(int i=1; i<=t; i++)
        {
            cin>>st[i];

            book[st[i]]=1;
        }


        for(int i=st[1]; i<=st[t]; i++)
        {
            if(!book[i])
            {
                for(int j=1; j<=t; j++)
                {
                    if(!edge[i][st[j]])
                    {

                        edge[i][st[j]]=1;


                        v[i].push_back(st[j]);

                        du[st[j]]++;

                    }
                }
            }
        }

        memset(book,0,sizeof(book));


    }


    for(int i=1; i<=n; i++)
    {
        if(!du[i])
        {
            q.push(i);

            dp[i]=1;
        }
    }
    int ans=1;

    while(!q.empty())
    {
        int now=q.front();

        q.pop();

        for(auto it:v[now])
        {
            du[it]--;
            if(du[it]==0)
                q.push(it);

            if(!dp[it])
                dp[it]=dp[now]+1;
            else
                dp[it]=max(dp[it],dp[now]+1);

            ans=max(ans,dp[it]);
        }
    }

    cout<<ans;
    return 0;
}
[HNOI2015]菜肴制作

两种贪心方法,第一种是放进小根堆,把最小的先输出。但会被hack,例如

(5,2)  (4,3)  输出  1 4 3 5 2 实际上应该是   1 5 2 4 3。

第二种就是放进大根堆,建立反图,倒着输出

(5,2) (4,3)      ->  (2,5)  (3,4) ->  3 4 2 5 1   -> 1 5 2 4 3 

这样就OK了

# include <iostream>
# include<algorithm>
# include<cstring>
# include<vector>
# include<queue>

using namespace std;
typedef long long int ll;

vector<int>v[100000+10];
int du[100000+10];
priority_queue<int>q;
int ans[100000+10];
int main()
{


      int t;

      cin>>t;

      while(t--)
      {
          int n,m,len;

          cin>>n>>m;

          while(!q.empty())
            q.pop();

          for(int i=1;i<=n;i++)
          {
              v[i].clear();

              du[i]=0;
          }

          for(int i=1;i<=m;i++)
          {
              int x,y;

              cin>>x>>y;

              v[y].push_back(x);

              du[x]++;

          }
          
          for(int i=1;i<=n;i++)
          {
              if(du[i]==0)
                q.push(i);
          }
          len=0;
          
          while(!q.empty())
          {
              int now=q.top();
              len++;
              ans[len]=now;
              q.pop();
              
              for(auto it:v[now])
              {
                  du[it]--;
                  
                  if(!du[it])
                    q.push(it);
              }
          }
          
          if(len!=n)
          {
              cout<<"Impossible!"<<endl;
              continue;
          }
          for(int i=len;i>=1;i--)
          {
              cout<<ans[i]<<" ";
          }

          cout<<endl;
      }

    return 0;
}
迷宫2

基于迪杰斯特拉的BFS,为了能够拦截,必须上下左右连续建造墙,从第一整列,第n整行开始扩展,每次选取最小花费的点,只能上下左右移动,一旦到达第一行或者第m列,拦截成功。细节较多,要开ll

#include <queue>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long ll;

int nx[4]= {0,0,-1,1};
int ny[4]= {1,-1,0,0};
int n,m;
bool check(int x,int y)
{
    return (x>=1&&x<=n&&y>=1&&y<=m);
}
ll mp[510][510], rem[510][510], inf=1e18,edge[510][510];
struct node
{
    int x,y;

    ll cost;
    friend bool operator<(node a, node b)
    {
        return a.cost>b.cost;
    }
};
priority_queue<node>q;
bool book[510][510];
int main ()
{

    int t;

    cin>>t>>n>>m;
    while(t--)
    {
        
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                cin>>mp[i][j];

                if(mp[i][j]==0)
                    mp[i][j]=-1;

                else if(mp[i][j]==-1)
                    mp[i][j]=0;

                rem[i][j]=inf;
            }
        }

        memset(book,0,sizeof(book));

        for(int i=1; i<=n; i++)
        {
            if(mp[i][1]==-1)
                continue;

            struct node now;

            now.x=i;
            now.y=1;

            if(mp[i][1]==0)
            {
                now.cost=0;
                rem[i][1]=0;
                book[i][1]=1;
            }
            else
            {
                now.cost=mp[i][1];
                rem[i][1]=now.cost;
                book[i][1]=1;
            }
            q.push(now);

        }


        for(int i=1; i<=m; i++)
        {
            if(mp[n][i]==-1)
                continue;

            struct node now;

            now.x=n;
            now.y=i;
            if(mp[n][i]==0)
            {
                now.cost=0;
                rem[n][i]=0;
                book[n][i]=1;
            }
            else
            {
                now.cost=mp[n][i];
                rem[n][i]=now.cost;
                book[n][i]=1;
            }

            q.push(now);

        }


        ll ans=-1;

        while(!q.empty())
        {
            struct node now=q.top();
            q.pop();

            if(now.x==1||now.y==m)
            {
                ans=now.cost;
                break;
            }

            for(int i=0; i<4; i++)
            {
                int xx=now.x+nx[i];
                int yy=now.y+ny[i];
                if(!check(xx,yy))
                    continue;

                if(mp[xx][yy]==-1)
                    continue;
                if(rem[xx][yy]>now.cost+mp[xx][yy])
                {

                    rem[xx][yy]=now.cost+mp[xx][yy];
                    struct node tail;
                    book[xx][yy]=1;
                    tail.x=xx;
                    tail.y=yy;
                    tail.cost=rem[xx][yy];
                    q.push(tail);

                }
            }
        }

        while(!q.empty())
            q.pop();

        cout<<ans<<endl;


    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秦三码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值