题意
在空洞骑士中,小骑士封印了最终boss辐光。圣巢又一次迎来了和平。但是经历了辐光的感染后,圣巢的很多设施都报废掉了。小姐姐大黄蜂作为圣巢之子,担负着重建圣巢的使命。其中一个任务,就是修复一些连接各个村庄的坍塌的双向鹿角虫通道。小姐姐希望用最少的人力(即修复最短的通道距离),使圣巢的各个村庄之间再次互相连通(直接连通或者间接连通)。
我们现在知道有一些村庄的鹿角虫通道依旧完好,请问你能帮助大黄蜂小姐姐来计算出最少的花费吗?
Input
第一行有一个整数N (3 <= N <= 100),表示村庄的个数。之后是N行数据,第i行有N个整数,该行的第j个整数表示村庄i与j之间的距离。距离的长度在 [1, 1000]范围内。
之后是一个整数Q(0 <= Q <= N * (N + 1) / 2). 之后是Q行,每一行包括两个整数a,b (1 <= a < b <= N)表示村庄a与村庄b仍有一个完好的鹿角虫通道
Output
你需要输出一个整数,来表示连通各个村庄的最少花费
分析:求最小生成树,完好的路径花费为0
#include
#include
using namespace std;
struct edge
{
int u,v,w;
};
struct edge e[20001];
int n,m;
int f[5001]={0},sum=0;
int cmp(edge x,edge y)
{
return x.w<y.w;
}
int getf(int v)
{
if(f[v]==v)
return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}
int merge(int v,int u)
{
int t1,t2;
t1=getf(v);
t2=getf(u);
if(t1!=t2)
{
f[t2]=t1;
return 1;
}
return 0;
}
int main()
{
int count=0;
int flag=0;
int i;
scanf("%d",&n);
int index;
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&index);
e[++cnt].u=i,e[cnt].v=j,e[cnt].w=index;
}
for(i=1;i<=n;i++)
f[i]=i;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
e[++cnt].u=a,e[cnt].v=b,e[cnt].w=0;
}
sort(e+1,e+1+cnt,cmp);
for(i=1;i<=cnt;i++)
{
if(merge(e[i].u,e[i].v))//寻找未连通的边,并联通
{
count++;
sum+=e[i].w;
}
if(count==n-1)//得到n-1边则成功
{
flag=1;
break;
}
}
printf("%d",sum);
return 0;
}
题意
格林剧团发工资的时候又到辣,格林剧团来到了圣巢,他们入乡随俗,将工资用圣巢的货币–吉欧来结算。格林团长决定每个人的最低工资是888吉欧,同时有些工人希望自己的工资要比其他某个人的高。格林团长希望在尽可能的少发工资的同时满足其他所有人的需求。请你帮帮格林团长吧,格林团长会邀请你与其在剧团内共舞一场猩红仪式。
Input
题目包含多组输入 第一行输入两个整数n,m,分别表示工人的数量与需求的个数。 接下来m行,每一行都包含两个整数a和b,表示a的工资必须比b的工资高
Output
对于每一组输入,输出格林团长最少花费的吉欧数量。如果格林团长不能满足所有人的需求,输出-1.
分析:拓扑排序,找到每个人所在的等级
#include
#include
#include
#include
#include
#define intn long long
#define _0for(i, a) for(int i = 0; i < (a); ++i)
#define _1for(i, a) for(int i = 1; i <=(a); ++i)
using namespace std;
int main()
{
int n, m;//节点数 边数
vector<vector<int>> G; //图
vector<int> in;//入度数
while (cin >> n >> m)
{
if (n == 0 && m == 0) { break; }
G = vector<vector<int>>(n + 1); //有n个点
in = vector<int>(n + 1);
for (int i = 1, a, b; i <= m; i++)
{
cin >> b >> a; //生动形象 a>>b a指向b
G[a].push_back(b); //添加该点指向了什么点
in[b]++; //该点入度数+1
}
queue<pair<int,int>> q; pair<int,int>t;
int ans=0;
int cnt=0;
for (int i = 1; i <= n; i++)
if (in[i] == 0) { q.push(make_pair(i,888)); } //如果入度数为0则添加
while (!q.empty()) //bfs遍历
{
t = q.front(); q.pop();
cnt++;
ans+=t.second;
for (size_t i = 0; i < G[t.first].size(); i++) //寻找除去该点后还有那些入度数为0的点
{
in[G[t.first][i]]--;
if (in[G[t.first][i]] == 0) q.push(make_pair(G[t.first][i],t.second+1));
}
}
if(cnt!=n)//如果形成了环就永远不会入度为0,得不到n个人的等级
printf("-1\n");
else
{
printf("%d\n",ans);
}
}
}
dfs或者bfs
#include
#include
#define intn long long
#define _0for(i, a) for(int i = 0; i < (a); ++i)
#define _1for(i, a) for(int i = 1; i <=(a); ++i)
using namespace std;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
int book[10][10];
int a[10][10];
int mbu=99999999;
int bx[1000],by[1000];
int flag=0;
int ansx[100],ansy[100];
int djs(int x,int y,int s)
{
if(a[x][y]==1)
return 1;
if(x<1||y<1||x>5||y>5)
return 1;
if(book[x][y])return 1;
if(s>mbu)
return 1;
bx[s]=x,by[s]=y;
if(x==5&&y==5)
{
if(mbu>s)
{
mbu=s;
for(int i=1;i<=s;i++)
{
ansx[i]=bx[i];
ansy[i]=by[i];
}
}
return 1;
}
for(int i=1;i<=4;i++)
{
book[x][y]=1;
djs(x+dx[i],y+dy[i],s+1);
book[x][y]=0;
}
}
int main()
{
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
scanf("%d",&a[i][j]);
}
djs(1,1,1);
for(int i=1;i<=mbu;i++)
{
printf("(%d, %d)\n",ansx[i]-1,ansy[i]-1);
}
return 0;
}
#include
using namespace std;
bool sign = false;
int num[9][9];
void Input();
void Output();
bool Check(int n, int key);
int DFS(int n);
int main()
{
cout << "请输入一个9*9的数独矩阵,空位以0表示:" << endl;
Input();
DFS(0);
Output();
system("pause");
}
void Input()
{
char temp[9][9];
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
cin >> temp[i][j];
num[i][j] = temp[i][j] - '0';
}
}
}
void Output()
{
cout << endl;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
cout << num[i][j] << " ";
if (j % 3 == 2)
{
cout << " ";
}
}
cout << endl;
if (i % 3 == 2)
{
cout << endl;
}
}
}
bool Check(int n, int key)
{
for (int i = 0; i < 9; i++)
{
int j = n / 9;
if (num[j][i] == key) return false;
}
for (int i = 0; i < 9; i++)
{
int j = n % 9;
if (num[i][j] == key) return false;
}
int x = n / 9 / 3 * 3;//注意理解
/* y为n所在的小九宫格左顶点横坐标 */
int y = n % 9 / 3 * 3;
/* 判断n所在的小九宫格是否合法 */
for (int i = x; i < x + 3; i++)
{
for (int j = y; j < y + 3; j++)
{
if (num[i][j] == key) return false;
}
}
/* 全部合法,返回正确 */
return true;
}
/* 深搜构造数独*/
int DFS(int n)
{
/* 所有的都符合,退出递归 */
if (n > 80)
{
sign = true;
return 0;
}
/* 当前位不为空时跳过 */
if (num[n/9][n%9] != 0)//n与行和列的关系
{
DFS(n+1);
}
else
{
/* 否则对当前位进行枚举测试 */
for (int i = 1; i <= 9; i++)
{
/* 满足条件时填入数字 */
if (Check(n, i) == true)
{
num[n/9][n%9] = i;
/* 继续搜索 */
DFS(n+1);
/* 返回时如果构造成功,则直接退出 */
if (sign == true) return 0;
/* 如果构造不成功,还原当前位 */
num[n/9][n%9] = 0;
}
}
}
}
题意给你一个整数n。找出三个不同的整数a、b、c,使得2≤a、b、c和a⋅b⋅c=n,或者说这是不可能的。
如果有几个答案,你可以打印任何答案。
你必须回答独立的测试用例。
Input
输入的第一行包含一个整数t(1≤t≤100)-测试用例的数量。
接下来的n行描述测试用例。第i个测试用例作为一个整数n(2≤n≤10^9)在新的一行上给出。
Output
对于每个测试用例,在上面打印答案。如果无法将某些不同整数a、b、c的n表示为a⋅b⋅c,使2≤a、b、c,则打印“NO”。
否则,打印“YES”和任何可能的此类表示。
分析:枚举a,b
#include
#include
#include
#include
#include
#define intn long long
#define _0for(i, a) for(int i = 0; i < (a); ++i)
#define _1for(i, a) for(int i = 1; i <=(a); ++i)
using namespace std;
main(void)
{
int t,n;
cin>>t;
for(int p=1;p<=t;p++)
{
cin>>n;
int flag=0;
for(int a=2;a*a*a<=n;a++)
{
if(n%a==0)
{
int bc=n/a;
for(int b=a+1;b*b<bc;b++)
{
if(bc%b==0)
{
if(flag==0)printf("YES\n");
flag++;
printf("%d %d %d\n",a,b,bc/b);
break;
}
}
if(flag)break;
}
}
if(flag==0)
printf("NO\n");
}
}
题意
LCM的指两个数的最小公倍数
现在XHK手上有一个X
请你找到这样的一对数(a,b),使得LCM(a,b)=x,并且max(a,b)要尽可能的小
Input
输入只包含一个数X(X<=1e12)
Output
输出包含两个数字a,b
x等于两个质数的积
题意
每个在圣巢的容器骑士都会希望成为最纯粹的容器。在 N (1 <= N <= 10,000) 个骑士里, 给定M (1 <= M <= 50,000) 个有序数对 (A, B)表示A认为B是纯粹的. 这种关系具有传递性, 如果A认为B是纯粹的,B认为C是纯粹的,那么A就认为C是纯粹的。被其他所有骑士都认定为纯粹的骑士,就将成为纯粹容器。
Input
第一行给定两个整数N和M 接下来的M行,每行两个整数A和B,表示A认为B是纯粹的。
Output
输出有多少个纯粹容器。
分析:tarjan算法缩点,然后统计出度,如果出度为0的点(最后到达)有1个,那么他的数量就纯粹容器的数量,如果多于一个就没有纯粹容器
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=10020;
vector<int>g[maxn];
int dfn[maxn],low[maxn],ins[maxn],bl[maxn],num,numb,nums[maxn];
int od[maxn];
stack<int>st;
void tarjan(int x)
{
dfn[x]=low[x]=++num;
ins[x]=1;
st.push(x);
for(int i=0;i<g[x].size();i++)
{
int q=g[x][i];
if(dfn[q]==0)
{
tarjan(q);
low[x]=min(low[q],low[x]);
}
else if(ins[q]==1)
{
low[x]=min(low[x],dfn[q]);
}
}
if(dfn[x]==low[x])
{
numb++;
int p;
do
{
p=st.top();
st.pop();
bl[p]=numb;
nums[numb]++;
ins[p]=0;
}
while(x!=p);
}
}
int main()
{
int n,m,i,x,y,j,v;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i){
scanf("%d%d",&x,&y);
g[x].push_back(y);
}
memset(dfn,0,sizeof(dfn));
for(i=1;i<=n;++i)if(!dfn[i])tarjan(i);
for(i=1;i<=n;++i)
for(j=0;j<g[i].size();++j){
v=g[i][j];
if(bl[i]!=bl[v])od[bl[i]]++;
}
x=0;
for(i=1;i<=numb;++i)
if(!od[i]){
if(x>0){
printf("0");
return 0;
}
x=nums[i];
}
printf("%d",x);
return 0;
}