#深搜#SSL 1116 洛谷 1475 控制公司

从半年前开始,我对这道题产生了极大的恐惧,作为蒟蒻的我,好难啊,现在学了邻接表,一切so easy。


题目

公司A控制公司B的原则

  1. 公司A拥有大于50%的公司B的股票。
  2. 公司A控制K(K >= 1)个公司,记为C1至CK,每个公司Ci拥有xi%的公司B的股票,并且 ∑ x 1 x k \sum^{xk}_{x1} x1xk>50%。

输出若干个的控制其他公司的公司。每行包括两个整数表明第一个整数的公司控制了第二个整数的公司。将输出的每行以第一个数字升序排列,并且第二个数字也升序排列。


分析

这道题用深搜,广搜都行,如果>50%那么往后并标记


深搜代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define N 100
using namespace std;
struct node{
	int x,y,w,next;
}e[N*100+1]; bool v[N+1];
int n,dis[N+1],ls[N+1];
int in(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
} 
void dfs(int i){
	int t=ls[i];
	while (t){//增加
		dis[e[t].y]+=e[t].w;
		t=e[t].next;
	}
	t=ls[i];
	while (t){
		if (dis[e[t].y]>50&&!v[e[t].y]){//属于被控制的吗?
			v[e[t].y]=1;
			dfs(e[t].y);
			v[e[t].y]=0;
		}
		t=e[t].next;
	}
}
int main(){
	n=in();
	for (int i=1;i<=n;i++) e[i].x=in(),e[i].y=in(),e[i].w=in(),e[i].next=ls[e[i].x],ls[e[i].x]=i;//邻接表
	for (int i=1;i<=100;i++)
	if (ls[i]){//可以往下走
		memset(dis,0,sizeof(dis));
		v[i]=1; dfs(i); v[i]=0;
		for (int j=1;j<=100;j++)
		if (dis[j]>50&&i!=j) printf("%d %d\n",i,j);//公司被控制
	}
	return 0;
}

#广搜代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define N 100
using namespace std;
struct node{
	int x,y,w,next;
}e[N*100+1]; bool v[N+1];
int n,dis[N+1],ls[N+1];
int in(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
} 
void spfa(int st){//名字怪异,不要在意
	int head=0,tail=1,list[N+1]; list[1]=st;
	do{
		head=head%N+1;//出队
		int t=ls[list[head]];
		while (t){
			dis[e[t].y]+=e[t].w;
			if (dis[e[t].y]>50&&!v[e[t].y]){//加入队列
				v[e[t].y]=1;
				tail=tail%N+1;
				list[tail]=e[t].y;
			}
			t=e[t].next;
		}
	}while (head!=tail);
}
int main(){
	n=in();
	for (int i=1;i<=n;i++) e[i].x=in(),e[i].y=in(),e[i].w=in(),e[i].next=ls[e[i].x],ls[e[i].x]=i;
	for (int i=1;i<=100;i++)
	if (ls[i]){
		memset(dis,0,sizeof(dis));
		memset(v,0,sizeof(v));
		v[i]=1; spfa(i);
		for (int j=1;j<=100;j++)
		if (dis[j]>50&&i!=j) printf("%d %d\n",i,j);
	} 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值