这场打的也不好(貌似也没有打的好的)、
题目好难补QAQ
1005
题意:给出一个无向图,要求任意两点之间至少存在一种方式可达,就是说要么存在u > v 要么存在v > u 要么都存在
思路:可以想象要形成这样的关系最终一定要是一条链,那么我们用tarjan后判断是否是一条链即可
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<LL, LL>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1005 + 5;
const int INF = 1e9 + 10;
vector<int> vt[qq], kt[qq];
int n, m, Bcnt, top, Index;
int fa[qq], dfn[qq], low[qq], Stack[qq], belong[qq], indeg[qq];
bool instack[qq];
void Init() {
mst(dfn, 0);
mst(fa, -1);
mst(indeg, 0);
mst(low, 0);
mst(belong, 0);
mst(instack, false);
Bcnt = top = Index = 0;
for(int i = 0; i <= n; ++i) {
vt[i].clear();
kt[i].clear();
}
}
int Find(int x) {
return fa[x] == -1 ? x : fa[x] = Find(fa[x]);
}
void Tarjan(int u) {
low[u] = dfn[u] = ++Index;
instack[u] = true;
Stack[top++] = u;
int sz = (int)vt[u].size();
for(int i = 0; i < sz; ++i) {
int v = vt[u][i];
if(!dfn[v]) {
Tarjan(v);
low[u] = min(low[u], low[v]);
} else if(instack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
int v;
if(low[u] == dfn[u]) {
++Bcnt;
do {
v = Stack[--top];
instack[v] = false;
belong[v] = Bcnt;
} while(v != u) ;
}
}
void VOA() {
queue<int> Q;
for(int i = 1; i <= Bcnt; ++i) {
if(indeg[i] == 0) Q.push(i);
}
int cnt = 0;
bool f = true;
while(!Q.empty()) {
if(Q.size() > 1) {
f = false;
break;
}
int u = Q.front();
Q.pop();
for(int i = 0; i < (int)kt[u].size(); ++i) {
int v = kt[u][i];
indeg[v]--;
if(indeg[v] == 0) Q.push(v);
}
}
if(f) puts("I love you my love and our love save us!");
else puts("Light my fire!");
}
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
Init();
int a, b;
for(int i = 0; i < m; ++i) {
scanf("%d%d", &a, &b);
vt[a].pb(b);
int x = Find(a), y = Find(b);
if(x != y) fa[y] = x;
}
int p = 0;
for(int i = 1; i <= n; ++i) {
if(fa[i] == -1) p++;
}
if(p > 1) {
puts("Light my fire!");
continue;
}
for(int i = 1; i <= n; ++i) {
if(!dfn[i]) Tarjan(i);
}
if(Bcnt == 1) {
puts("I love you my love and our love save us!");
continue;
}
for(int i = 1; i <= n; ++i) {
for(int j = 0; j < (int)vt[i].size(); ++j) {
if(belong[i] == belong[vt[i][j]]) continue;
indeg[belong[vt[i][j]]]++;
kt[belong[i]].pb(belong[vt[i][j]]);
}
}
VOA();
}
return 0;
}
1008
题意:原本有个数组a, 然后所有(ai + aj)就构成了数组b(1 <= i < j <= n),现在数组a的元素和素数b的元素混到一起了求出原来的数组a
思路:排序之后最前面两个一定出现在数组a中,然后用一个mp维护一定出现在数组a中的元素构成的数组b中的元素、
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<LL, LL>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 125250 + 5;
const int INF = 1e9 + 10;
int num[qq], ans[qq];
map<int, int> mp;
int main(){
int n;
while(scanf("%d", &n) != EOF) {
mp.clear();
for(int i = 0; i < n; ++i) {
scanf("%d", num + i);
}
if(n == 0) {
printf("0\n");
continue;
} else if(n == 1) {
printf("1\n%d\n", num[0]);
continue;
}
sort(num, num + n);
int cnt = 0;
ans[cnt++] = num[0], ans[cnt++] = num[1];
mp[ans[0] + ans[1]]++;
for(int i = 2; i < n; ++i) {
if(mp[num[i]]) {
mp[num[i]]--;
} else {
ans[cnt++] = num[i];
for(int i = 0; i < cnt - 1; ++i) {
mp[ans[cnt - 1] + ans[i]]++;
}
}
}
printf("%d\n", cnt);
for(int i = 0; i < cnt; ++i) {
printf("%d%c", ans[i], i == cnt - 1 ? '\n' : ' ');
}
}
return 0;
}