愚者指名自己的辩护人

寒假模拟3的一道图论题
和概率沾点边不过本意不是考概率
这里要求一个概率最大问题
如果删去某个点使得概率会下降的话,那么这个点必选
因为加入这点以后会使最优解更优
然后就可以愉快的跑Floyd了hhh
考虑到n=100,O(n^4)差不多是极限数据
如果硬跑Floyd控制不好常数或者控制不好低次项就会T掉
然后emo一整天
所以我们可以压一下时间复杂度
对于n=100,m=200来说,上个SPFA跑最长路随便过
y1s1,SPFA真的啥都能跑就是不能跑极限数据菊花图
所以就搬来wenqizhi大佬的一个SPFA做法
感谢大佬%%%wenqizhi tql orz

点击查看代码
#include <bits/stdc++.h>
using namespace std;
bool zhao[1000][1000];
int n,m;//点数,边数 
double a[1000];//每个点的安全概率 
vector<int> gg[1000];//每个点的前驱,可能不止一个
//存边 
struct sb{
	int u,v,next;
}xing[1000];
int head[1000];
int cnt;
void add(int u,int v){
	++cnt;
	xing[cnt].next=head[u];
	head[u]=cnt;
	xing[cnt].u =u;
	xing[cnt].v =v;
}

struct node{
	int dian;
	double dis;
	node(){}
	node(int a,double b):dian(a),dis(b){}
	bool friend operator < (node a,node b){
		return a.dis < b.dis;
	}
};

double dis[1000];
bool vis[1000];

void spfa(int k){
	priority_queue<node> xx;
	node dq;
	vis[k]=true;
	dis[k]=a[k];
	xx.push(node(k,a[k]));
	while (!xx.empty()){
		dq=xx.top();
		xx.pop();
		int x=dq.dian;
		vis[x]=false;
		for (int i=head[x];i;i=xing[i].next ){
			int v=xing[i].v ;
			int yuan=(int)(dis[v]*10000000);
			int xian=(int)(dis[x]*a[v]*10000000);
			if(yuan<xian){
				dis[v]=dis[x]*a[v];
				gg[v].clear();
				gg[v].push_back(x);
				if(vis[v]==false){
					xx.push(node(v,dis[v]));
					vis[v]=true;
				}
			}else if(yuan==xian){
				gg[v].push_back(x);
			}
		}
	}
}

int qian[1000];//记录被作为前驱的次数 
int main (){
	freopen("fool.in","r",stdin);
	freopen("fool.out","w",stdout);
	int d;
	scanf ("%d %d",&n,&m);
	for (int i=1;i<=n;++i){
		scanf ("%d",&d);
		a[i]=1-(double)d/100;
		//初始化很小 
		dis[i]=0;
	}
	int s1,s2;
	for (int i=1;i<=m;++i){
		scanf ("%d %d",&s1,&s2);
		if(zhao[s1][s2]==true||zhao[s2][s1]==true) continue;
		zhao[s1][s2]=true;
		zhao[s2][s1]=true;
		add(s1,s2);
		add(s2,s1);
	}
	spfa(1);
	//记录前驱,记录每个点被作为前驱的次数,和1的次数相等即为必经之路 
	queue<int> ll;
	//先把终点处理 
	for (int i=0;i<gg[n].size();++i){
		ll.push(gg[n][i]);
		++qian[gg[n][i]];
	}
	int dq;
	while (!ll.empty()){
		dq=ll.front();
		ll.pop();
		for (int i=0;i<gg[dq].size();++i){
			ll.push(gg[dq][i]);
			++qian[gg[dq][i]];
		}
	}
	printf ("1\n");
	for (int i=2;i<n;++i){
		if(qian[i]==qian[1]){
			printf ("1\n");
		}else {
			printf ("0\n");
		}
	}
	printf ("1\n");
	return 0;
}
posted @ 2022-02-17 20:51  2K22  阅读(18)  评论(1)    收藏  举报