题意
题解
代码
#include
#include
using namespace std;
const int N=105,M=10010;
int n,m,s,t;
int h[N],e[2*M],ne[2*M],idx;//图的存储结构
int st[N];
int q[M];//队列数组
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool bfs()
{
memset(st,0,sizeof st);//初始化
int hh=0,tt=-1;//初始化队列
q[++tt]=t;//起点入队
while(hh<=tt){//宽搜
int x=q[hh++];//取出队头
for(int i=h[x];i!=-1;i=ne[i]){//扩展队列
int j=e[i];st[j]++;
if(st[j]>=2){
q[++tt]=j;
if(j==s) return true;
}
}
}
return false;
}
void solve()
{
cin>>n>>m>>s>>t;
memset(h,-1,sizeof h); idx=0;//初始化邻接表
while(m--){
int a,b;
cin>>a>>b;
add(a,b);add(b,a);
}
cout<<(bfs() ? "Join Player":"Cut Player")<<'\n';
}
int main() {
int T;
cin>>T;
while(T--) solve();
return 0;
}
题意
题解
代码
#include
using namespace std;
#define int long long
const int N=1e6+10,mod=998244353;
int A,B,x,res=0;
int fac[2*N],infac[N],pow2[2*N];//阶乘,阶乘逆元(用来求组合数);2的幂
int qp(int a,int b) {//快速幂
int res=1;
while(b) {
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void init() {//初始化阶乘,阶乘逆元,2的幂
fac[0]=fac[1]=1;
for(int i=2;i<2*N;i++) fac[i]=fac[i-1]*i%mod;
infac[N]=qp(fac[N],mod-2);
for(int i=N-1;i;i--) infac[i]=infac[i+1]*(i+1)%mod;
pow2[0]=1;
for(int i=1;i<2*N;i++) pow2[i]=2*pow2[i-1]%mod;
}
int C(int a,int b) {//求组合数
if(a<b) return 0;
if(b==0) return 1;
if(a==b) return 1;
return fac[a]*infac[b]%mod*infac[a-b]%mod;
}
signed main() {
init();
cin>>A;
for(int i=0;i<7;i++) cin>>x;
cin>>B;
for(int i=0;i<7;i++) cin>>x;
A=(A+9)/10;B=(B+9)/10;//承受攻击次数
int res=0;
for(int i=0;i<A;i++) {//枚举a承受的攻击轮数,总轮数就是i+B
int ans=C(i+B-1,i)*qp(pow2[i+B],mod-2)%mod;//此种概率
res=(res+ans)%mod;//答案加和
}
cout<<res<<'\n';
return 0;
}
题意
题解
代码
#include
#include
#include
using namespace std;
const int N=1e6+5,M=1e7+5;
typedef pair<int,int> PII;
int n,m,a[N],b[N],posa[M],posb[M];//数组长度,数组,数组值的下标
int id[M],ai,aj,bi,bj;//判重数组,一组解4个下标
bool vis[2*M];//某个和是否存在过
PII mp[2*M];//某个和对应的a,b数组的两个下标
int main() {
cin.tie(0)->sync_with_stdio(false);
//特判有重复元素的情况
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],posa[a[i]]=i;
for(int i=1;i<=m;i++) cin>>b[i],posb[b[i]]=i;
for(int i=1;i<=n;i++) {
if(id[a[i]]) { ai=id[a[i]]; aj=i; break;}
id[a[i]]=i;
}
memset(id,0,sizeof id);
for(int i=1;i<=m;i++) {
if(id[b[i]]) { bi=id[b[i]]; bj=i; break;}
id[b[i]]=i;
}
if(ai && aj && bi && bj) {cout<<ai<<' '<<aj<<' '<<bi<<' '<<bj<<'\n'; return 0;}
//无重复元素解的情况
sort(a+1,a+1+n); n=unique(a+1,a+1+n)-(a+1);//去重
sort(b+1,b+1+m); m=unique(b+1,b+1+m)-(b+1);
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
int num=a[i]+b[j];
if(vis[num]) {
ai=mp[num].first,bi=mp[num].second;
aj=posa[a[i]],bj=posb[b[j]];
cout<<ai<<' '<<aj<<' '<<bi<<' '<<bj<<'\n';
return 0;
}
else {
vis[num]=1;
mp[num]={posa[a[i]],posb[b[i]]};
}
}
}
puts("-1");//无解
return 0;
}
题意
题解
代码
#include
#include
using namespace std;
const int N=405;
int n,m;
string s;
int h[N],e[N*N],ne[N*N],idx;//建图,注意数组大小
int st[N],match[N];//匈牙利
int cnt[N];//记录每个论文被几个审稿人审
void add(int a,int b) {//加边
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int x) {//能否为x稿子找到一个审稿人。匈牙利算法
for(int i=h[x];~i;i=ne[i]) {
int j=e[i];
if(!st[j]) {
st[j]=x;
if(!match[j] || find(match[j])) {
match[j]=x;
return true;
}
}
}
return false;
}
int main() {
cin.tie(0)->sync_with_stdio(false);
cin>>n>>m;
bool flag=1;//如果有审稿人一篇都不能审,那么不存在匹配
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++) {//审稿人
cin>>s;
bool f=0;
for(int j=0;j<m;j++)//论文
if(s[j]=='1') {//可审,加边
add(j+1,i);//只加男生指向女生的边,即论文->审稿人
f=1;
}
flag&=f;
}
if(!flag) { puts("-1"); return 0; }//没有匹配
int minn=0;//存在男的选到选minn个老婆
flag=1;//是否要进行下一轮的二分匹配
while(flag) {
flag=0;
for(int i=1;i<=m;i++) {//对于每个论文(男)找审稿人(女)
if(cnt[i]!=minn) continue;//如果这个男的都没有在上一轮找到老婆,那么这一轮也不能
memset(st,0,sizeof st);//二分匹配对于每个男的选择的时候,需要置空标记的st
if(find(i)) cnt[i]++,flag=1;//这个男的能找到老婆,老婆数量++;同时标记此轮二分匹配存在匹配成功,那么可以进行下一轮二分匹配
}
minn++;//每进行一轮都把标准++
}
for(int i=1;i<=n;i++) cout<<match[i]<<' ';//输出每个女生的配偶
puts("");
return 0;
}