题目:
Triangle LOVE
题意:给一个矩阵, G[i][j] == '1'表示i喜欢j,如果有a喜欢b,b喜欢c,c喜欢a,则称找到一个"三角恋",如果能找到的话输出yes。
注意i和j必有关系,不是i喜欢j就是j喜欢i(不同时)
思路:
这题不就是找环嘛,任意两个元素之间一定有关系,自然就想到了拓扑,这里有规律:一旦出现环,则必定出现三元环。所以只需判断有没有环就可以了。
再次复习一下:有环的条件:出队列的次数小于总元素个数,即中途出现没有入度为0的点的情况(此时就可以退出了,不必等到队列里的元素都出列)
代码:
两种风格的代码
1.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
using namespace std;
typedef long long LL;
const long long LINF = (long long)1e30;
const int INF = 522133279;
const int MAXN = 100000+100;
#define eps 1e-14
const int mod = 500000;
vector<int> G[2010];
int in[2010];
int n;
char a[2010];
bool top()
{
queue<int> que;
int cnt=0; //出队次数
for(int i = 0 ; i < n ; i++)
if(in[i]==0)
que.push(i);
if(que.empty())
return true;
while(!que.empty())
{
int tmp = que.front();
que.pop();
cnt++;
int ok=0;
for(int i = 0 ; i < G[tmp].size() ; i++)
if(--in[G[tmp][i]] == 0)
{
ok=1;
que.push(G[tmp][i]);
}
if(!ok && cnt < n) //别忘了加上这句cnt < n , 无环时会有!ok&& cnt== n
return true;
}
return false;
}
int main()
{
//freopen("in","r",stdin);
//freopen("out","w",stdout);
int t;
scanf("%d",&t);
for(int ka = 1 ; ka <= t ; ka++)
{
memset(in,0,sizeof(in));
scanf("%d",&n);
for(int i = 0 ; i <= n ; i++)
G[i].clear();
for(int i = 0 ; i < n ; i++)
{
scanf("%s" , a); //这里注意,之前一个一个字符输入超时了
for(int j = 0 ; j < n ; j++)
{
if(a[j] == '1')
G[j].push_back(i),in[i]++;
}
}
bool ok = top();
if(ok)
printf("Case #%d: Yes\n",ka);
else
printf("Case #%d: No\n",ka);
}
return 0;
}
2:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
using namespace std;
typedef long long LL;
const long long LINF = (long long)1e30;
const int INF = 522133279;
const int MAXN = 100000+100;
#define eps 1e-14
const int mod = 100000007;
char G[2010][2010];
int in[2010];
int main()
{
//freopen("in","r",stdin);
int t;
scanf("%d",&t);
getchar();
for(int ka =1; ka <= t ; ka++)
{
memset(in,0,sizeof(in));
int ok=0;
int n;
scanf("%d" , &n);
for(int i = 0 ; i < n ; i++)
{
scanf("%s" , G[i]);
for(int j = 0 ; j < n ; j++)
if(G[i][j] == '1')
in[j]++;
}
for(int i = 0 ; i < n ; i++)
{
ok=0;
int cur=0;
for(int j = 0 ; j < n ; j++)
if(in[j] == 0) //不用队列的话,找到一个入度为0的就刷新相关点
{
ok=1;
cur=j;
break;
}
if(!ok)
break;
else
{
in[cur] = -10;
for(int k = 0 ; k < n ; k++)
if(G[cur][k] == '1' && in[k])
in[k]--;
}
}
if(!ok)
printf("Case #%d: Yes\n",ka);
else
printf("Case #%d: No\n",ka);
}
return 0;
}