2 条题解

  • 0
    @ 2026-9-23 15:04:12

    思路

    这道题的方法题目已经很明显了:拓扑排序 。

    由题意可得知水管只会从一边流向另一边(单向),因此可以判断每个挤奶器能流到哪些点,只要一个点所有挤奶器都能流过,就可以输出,但是题目说混合机不能放在挤奶器的位置(入度为 00 的节点),所以需要用数组记录特判。

    对于牛奶来说,最多只有一种方式从一个接口流到另一个接口。

    所以分叉后的节点(出度大于 11 的子节点)只装一个混合机是无法将所有的牛奶混合的,只能装在分叉之前。


    我知道有些人就是来看这个的,你们喜欢的来了。

    代码

    #include<iostream>
    #include<vector>
    #include<cstdio>
    #include<queue>
    using namespace std;
    vector<int> v[100001];
    queue<int> q;
    int n,m,u,vl,l,a[100001],b[100001],c[100001];
    void topo() //拓扑排序。
    {
    	for(int i=1;i<=n;i++)
    	if(!a[i]) //判断挤奶器。
    	{
    		b[i]=c[i]=1;
    		q.push(i);
    		l++;
    	}
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		if(v[u].size()==1) //出度为零是储存室,出度大于一即为分叉,只有1出度才能继续往下搜(可以用另一种写法:continue)。
    		{
    			int vl=v[u][0];
    			b[vl]+=b[u];
    			a[vl]--;
    			if(!a[vl])
    			 q.push(vl);
    		}
    	}
    }
    int main()
    {
    	cin>>n;
    	m=n-1;
    	for(int i=1;i<=m;i++) //建边。
    	{
    		scanf("%d%d",&u,&vl);
    		v[u].push_back(vl);
    		a[vl]++;
    	}
    	topo();
    	for(int i=1;i<=n;i++)
    	if(!c[i]&&b[i]==l) //判断输出,c数组判断是否是挤奶器,b数组判断有几个挤奶器的奶能经过这个点。
    	 printf("%d\n",i);
    }
    

    题解求管理大大通过。

    • 0
      @ 2025-10-8 16:58:03
      #include<bits/stdc++.h>
      using namespace std;
      const int N=1e5+10;
      vector<int>G[N];
      queue<int>q;
      int ind[N],f[N],milk[N];
      bool ism[N];
      int n,m,sum;
      void topo()
      {
          sum=0;memset(ism,0,sizeof(ism));memset(milk,0,sizeof(milk));
          for(int i=1;i<=n;i++)
          {
              if(!ind[i])
              {
                  q.push(i);
                  ism[i] = true;   //标记源点 
                  milk[i] = 1;     //记录每个源点的流量
                  sum++;           //一共有多少个源点(总流量)
              }
          }
          while(!q.empty())
          {
              int x= q.front();q.pop();
              if(G[x].size()>1) continue;   //某点的出度大于1,说明该点的后继节点不可能为关键点 
              for(int y:G[x])
              {
                  ind[y]--;
                  milk[y]+=milk[x];
                  if(!ind[y]) q.push(y);
              }
          }
      }
      int main()
      {
          scanf("%d",&n);
          for(int i=1,x,y;i<n;i++)
          {
              scanf("%d%d",&x,&y);
              G[x].push_back(y);
              ind[y]++;
          }
          topo();
          for(int i=1;i<=n;i++)
          {
              if(!ism[i]&&milk[i]==sum) //不是源点且来自所有源点的流量都流经该点 
              {
                  printf("%d\n",i);
              }
          }
          return 0;
      }
      
      • 1

      【拓扑】关键点[USACO10NOV] Chocolate Milk S

      信息

      ID
      1580
      时间
      1000ms
      内存
      128MiB
      难度
      9
      标签
      递交数
      10
      已通过
      4
      上传者